JS如何取得URL裏的參數?

有一段時間沒寫過技術乾貨文了,這兩天恰好遇到一個之前沒太在乎的一個功能實現--前端獲取URL傳遞的參數前端

畢竟平時都是在後臺處理,掉了一堆頭髮後,想一想仍是寫出來跟大家分享一下,之後要是大家遇到了也有個參考正則表達式

要只是獲取一些常規字符串到沒什麼難的,關鍵還有些亂七八糟的需求,什麼同一個參數名傳遞了屢次啊,傳數組啊。搞來搞去就寫了一大堆數組

先說說思路吧,若是你看這文章是想要解決問題,拿着代碼直接用的話,就直接看最後面的Code實現以及使用方法吧瀏覽器

用框架思惟分析問題

給你一個以下的URL:微信

NaoNao.com/?product=sh…框架

將URL裏傳遞的參數轉換爲object對象,這樣咱們在使用參數的時候也更爲方便函數

我曾屢次強調框架思惟,如今遇到這個問題了,咱們就拿框架思惟來分析一下,該怎樣才能快速解決學習

首先是要了解咱們的目的是什麼?目的很簡單,取得URL內傳遞的參數,而且解析成對象ui

接着再分析咱們如今知道些什麼?有一串URLurl

咱們再來分析,若是從URL中得到傳遞的參數,也就是爲了達到目的,咱們該作些什麼?

URL的特徵咱們大體都知道,就是第一個?後面的字符串,都是傳遞的參數,可是有個特殊狀況請不要忘記了,URL後面有時候會帶上一個#,而#後面的內容,並非咱們要傳遞的參數,而是網頁位置的標識符

若是URL中包含了#咱們只須要解析?#之間的字符串就能夠了,若是不包含,那麼第一個?後全部的內容都是咱們須要解析的

你可能以爲我是在說廢話,這麼明顯的事情,只要不是白癡都能看得懂

我固然知道,只要不是白癡都能看得懂,但我爲何要強調呢?由於咱們想要快速的解決問題,必須具有框架思惟,也能夠說是工程思惟

你可能有會說,這麼簡單的問題須要這樣分析麼?咱們一看就知道了,鬧鬧你這是殺雞用牛刀

雖然說是殺雞用牛刀,可要想培養本身的工程思惟,那麼必須保持刻意訓練,直到隨手拈來

好了,分析完後,咱們按照上面的思路來逐步實現,實現的時候可能會遇到其它的問題,到時候再分析,再解決

畢竟再牛逼的工程師,也不會在動手前就想的面面俱到,只能是在動手實現前儘量的考慮周到,遇到問題時再快速的迭代更新

JS獲取URL參數的過程

先用JS拿到URL,若是函數傳參了URL,那就用參數。若是沒傳參,就使用當前頁面的URL

var queryString = url ? url.split('?')[1] : window.location.search.slice(1);
複製代碼

若是後面的字符串存在#,咱們還得將#後面的字符串去掉,由於#後面的內容並非咱們須要獲取的參數,而是網頁位置的標識符

queryString = queryString.split('#')[0];
複製代碼

好了,把干擾的部分都移除後,咱們能夠開始安心的解析參數了,先將傳遞的參數分紅數組

var arr = queryString.split('&');
複製代碼

如今咱們能夠得到一個字符串數組

['product=shirt', 'color=blue', 'newuser', 'size=m']
複製代碼

將字符串拆分紅數組後,咱們經過建立一個對象,用來存儲咱們全部的參數

var obj = {};
複製代碼

咱們能夠經過遍歷數組arr,將它拆分紅鍵值對。把這個字符串作成key:value的對象

var a = arr[i].split('=');
複製代碼

接下來就是要爲每個變量key分配對應的值value,若是咱們獲得的value不是一個正確的參數,咱們就用true來表示這個參數名存在,固然了,你也能夠根據本身的實際狀況來作改變

var paramName = a[0];
var paramValue = typeof(a[1]) === 'undefined' ? true : a[1];
複製代碼

在這裏我只是對undefined作了標記,若是是NaN,我是直接拿它當字符串處理了

在這裏有一個小坑得提醒一下,咱們在調用函數,獲取對象取值的時候,若是URL傳遞的key爲大寫,咱們取對象時寫的小寫,那麼結果就是爲undefined

好比URL爲http://NaoNao.com/?NamE=NaoNao,若是不作大小寫的處理,調用對象取值時getAllUrlParams().NamE才能取到值NaoNao,若是作了處理,咱們使用時只須要所有寫成小寫/大寫便可,例如getAllUrlParams().name

我在這就所有轉爲小寫了,若是你對大小寫要求區分,那到時候把這段Code給去掉就行了

paramName = paramName.toLowerCase();
if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();
複製代碼

接下來咱們就要去處理咱們接受到的paramValue這些參數多是索引數組,非索引數組,又或者是常規字符串

若是是索引數組,咱們須要將paramValue轉換成數組,而且將索引對應的值,放入索引對應的位置

若是是非索引數組,咱們就要將paramValue放到數組中

若是隻是常規的字符串,咱們就須要爲咱們的對象obj建立一個常規的屬性,併爲其分配值。

若是這個key已經存在,那麼咱們就要將現有的paramValuekey:value轉換爲數組,並將它放到數組中

拿幾個實際案例,感覺一下咱們要作什麼吧

// 索引數組
getAllUrlParams('http://NaoNao.com/?colors[0]=red&colors[2]=green&colors[6]=blue');
// { "colors": [ "red", null, "green", null, null, null, "blue" ] }

// 非索引數組
getAllUrlParams('http://NaoNao.com/?colors[]=red&colors[]=green&colors[]=blue');
// { "colors": [ "red", "green", "blue" ] }

// 屢次傳遞同一個key
getAllUrlParams('http://NaoNao.com/?colors=red&colors=green&colors=blue');
// { "colors": [ "red", "green", "blue" ] }

// 傳遞了key,可是沒傳value
getAllUrlParams('http://NaoNao.com/?product=shirt&color=blue&newuser&size=m');
// { "product": "shirt", "color": "blue", "newuser": true, "size": "m" }
複製代碼

我作這寫判斷時用的是正則表達式,在這裏就不解釋正則了。。。畢竟解釋起來篇幅就太長了,能看懂就儘可能看吧

每一個正則要解析什麼,在註釋中都寫了例子,稍微瞭解點正則表達式的同窗,多半也能看懂的

對應的代碼實現以下:

// 若是paramName以方括號結束, e.g. colors[] or colors[2]
if (paramName.match(/\[(\d+)?\]$/)) {
    // 若是paramName不存在,則建立key
    var key = paramName.replace(/\[(\d+)?\]/, '');
    if (!obj[key]) obj[key] = [];
    // 若是是索引數組 e.g. colors[2]
    if (paramName.match(/\[\d+\]$/)) {
        // 獲取索引值並在對應的位置添加值
        var index = /\[(\d+)\]/.exec(paramName)[1];
        obj[key][index] = paramValue;
    } else {
        // 若是是其它的類型,也放到數組中
        obj[key].push(paramValue);
    }
} else {
    // 處理字符串類型
    if (!obj[paramName]) {
        // 若是若是paramName不存在,則建立對象的屬性
        obj[paramName] = paramValue;
    } else if (obj[paramName] && typeof obj[paramName] === 'string') {
        // 若是屬性存在,而且是個字符串,那麼就轉換爲數組
        obj[paramName] = [obj[paramName]];
        obj[paramName].push(paramValue);
    } else {
        // 若是是其它的類型,仍是往數組裏丟
        obj[paramName].push(paramValue);
    }
}
複製代碼

若是你的URL的傳參包含了一些特殊字符,好比空格。例如url="NaoNao.com/?name=Nao%20Nao",拿到對象值以後,是須要解碼後才能得到正確的值的

var original = getAllUrlParams().name; // 'Nao%20Nao'
var decode = decodeURIComponent(original); // 'Nao Nao'
複製代碼

具體實現以及使用方式

下面是JS的具體的完整實現,大家複製回去就能夠用

function getAllUrlParams(url) {
    // 用JS拿到URL,若是函數接收了URL,那就用函數的參數。若是沒傳參,就使用當前頁面的URL
    var queryString = url ? url.split('?')[1] : window.location.search.slice(1);
    // 用來存儲咱們全部的參數
    var obj = {};
    // 若是沒有傳參,返回一個空對象
    if (!queryString) {
        return obj;
    }
    // stuff after # is not part of query string, so get rid of it
    queryString = queryString.split('#')[0];
    // 將參數分紅數組
    var arr = queryString.split('&');
    for (var i = 0; i < arr.length; i++) {
        // 分離成key:value的形式
        var a = arr[i].split('=');
        // 將undefined標記爲true
        var paramName = a[0];
        var paramValue = typeof (a[1]) === 'undefined' ? true : a[1];
        // 若是調用對象時要求大小寫區分,可刪除這兩行代碼
        paramName = paramName.toLowerCase();
        if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();
        // 若是paramName以方括號結束, e.g. colors[] or colors[2]
        if (paramName.match(/\[(\d+)?\]$/)) {
            // 若是paramName不存在,則建立key
            var key = paramName.replace(/\[(\d+)?\]/, '');
            if (!obj[key]) obj[key] = [];
            // 若是是索引數組 e.g. colors[2]
            if (paramName.match(/\[\d+\]$/)) {
                // 獲取索引值並在對應的位置添加值
                var index = /\[(\d+)\]/.exec(paramName)[1];
                obj[key][index] = paramValue;
            } else {
                // 若是是其它的類型,也放到數組中
                obj[key].push(paramValue);
            }
        } else {
            // 處理字符串類型
            if (!obj[paramName]) {
                // 若是若是paramName不存在,則建立對象的屬性
                obj[paramName] = paramValue;
            } else if (obj[paramName] && typeof obj[paramName] === 'string') {
                // 若是屬性存在,而且是個字符串,那麼就轉換爲數組
                obj[paramName] = [obj[paramName]];
                obj[paramName].push(paramValue);
            } else {
                // 若是是其它的類型,仍是往數組裏丟
                obj[paramName].push(paramValue);
            }
        }
    }
    return obj;
}
複製代碼

這個函數該怎麼使用呢?

直接把URL參數當成對象調用就OK咯~

以文章開篇的URL爲例子

// http://NaoNao.com/?product=shirt&color=blue&newuser&size=m#Hello

getAllUrlParams().product; // 'shirt'
getAllUrlParams().color; // 'blue'
getAllUrlParams().newuser; // true
getAllUrlParams().NB; // undefined
getAllUrlParams('http://NaoNao.com/?NaoNao=shuai').NaoNao; // shuai
複製代碼

不兼容IE的解決方案

若是咱們不須要考慮IE這種妖嬈賤貨,以及一些很是老版本瀏覽器,就用瀏覽器內URLSearchParams的接口吧。。。這個接口能夠直接拿取URL內的參數

// URL is http://NaoNao.com/?product=shirt&color=blue&newuser&size=m
const urlParams = new URLSearchParams(window.location.search);
// 判斷參數是否存在
console.log(urlParams.has('product')); // true
// 獲取參數對應的值
console.log(urlParams.get('product')); // "shirt"
複製代碼

這個接口還提供了更多成熟的方法,好比keys(),Values(),還有entries(),這個接口該怎麼使用,直接去看官方文檔就行了,用起來仍是很虛浮的

微信掃碼關注公衆號「鬧鬧吃魚」,每週都有好分享,還可領取學習資源哦~不只僅只是技術!

相關文章
相關標籤/搜索