動態

詳情 返回 返回

URL參數的格式化和解析 - 動態 詳情

常見場景

傳遞 URL 參數是頁面A與頁面B通信時常用的方法。如:頁面A是新聞列表頁面,在點擊某一條新聞的時候,需要帶着新聞 ID 打開頁面B新聞詳情頁面 pageB?id=${id},這樣頁面B就能根據解析 URL 上的 ID 獲取具體的新聞詳情了。

常見的格式化和解析方法

🔥🔥🔥 推薦一個好用的解析工具:Prettier URL

給出一段參數:

const query = {
    a: 'a',
    b: 1,
    c:[1,2,3,{ cc: 'my_cc'}],
    d: {
        name:'name',
        value: { num: 1}    
    },
    e: "https://www.baidu.com?a=1&b=1#tag"
}

使用現有的庫

先拋出結論:推薦使用 qs

query-string

地址:https://www.npmjs.com/package/query-string

stringify
import queryString from 'query-string';
console.log(queryString.stringify(query));

結果(c=1&c=2&c=3):a=a&a%3F.b=a_b&b=1&c=1&c=2&c=3&c=%5Bobject%20Object%5D&d=%5Bobject%20Object%5D&e=https%3A%2F%2Fwww.baidu.com%3Fa%3D1%26b%3D1%23tag

使用 comma 格式 stringify
import queryString from 'query-string';
console.log(queryString.stringify(query),{arrayFormat: 'comma'});

結果(c=1,2,3):a=a&a%3F.b=a_b&b=1&c=1,2,3,%5Bobject%20Object%5D&d=%5Bobject%20Object%5D&e=https%3A%2F%2Fwww.baidu.com%3Fa%3D1%26b%3D1%23tag

parse

解析:

import queryString from 'query-string';
const str = queryString.stringify(query),{arrayFormat: 'comma'})
queryString.parse(`?${str}`)

返回:

{
  a: "a", 
  b: "1", 
  c:[ "1","2","3",[object Object]"], 
  d: "[object Object]", 
  e: "https://www.baidu.com?a=1&b=1#tag"
}
總結
  • 不需要手動去掉 location.search?
  • 數組處理支持 arrayFormat: 'bracket' | 'index' | 'comma'
  • 具備 encodeURIComponent(key)
  • 具備 encodeURIComponent(value)
  • 無法處理 value 為對象的情況( 被處理成 '[object Object]'),stringify + parse 後 這種值會丟失
  • 重複的 key 的解析 ?a=1&a=a { a: ["1","a"]}

querystring

image.png
已經被廢棄了,不要再使用了,這裏直接給出結論

  • 需要手動去掉 location.search?
  • 數組處理支持 arrayFormat: 'bracket' | 'index' | 'comma'
  • 具備 encodeURIComponent(key)
  • 具備 encodeURIComponent(value)
  • 無法處理 value 為對象的情況( 被處理成 '[object Object]'),stringify + parse 後 這種值會丟失
    • 重複的 key 的解析 ?a=1&a=a { a: ["1","a"]}

qs 【推薦】

github: https://github.com/ljharb/qs

stringify
import qs from 'qs';
console.log(qs.stringify(query));

結果:a=a&b=1&c%5B0%5D=1&c%5B1%5D=2&c%5B2%5D=3&c%5B3%5D%5Bcc%5D=my_cc&d%5Bname%5D=name&d%5Bvalue%5D%5Bnum%5D=1&e=https%3A%2F%2Fwww.baidu.com%3Fa%3D1%26b%3D1%23tag&a%3F.b=a_b

parse

解析:

import queryString from 'query-string';
const str = queryString.stringify(query),{arrayFormat: 'comma'})
queryString.parse(`?${str}`)

結果:

{
   a: "a"
   b: "1"
   c: ["1","2",{ cc: "my_cc"}]
  d: { name:"name", value:{} num: "1"}}
  e: "https://www.baidu.com?a=1&b=1#tag" 
}
總結
  • 需要手動去掉 location.search?
  • 數組處理支持 arrayFormat: 'indices' | 'bracket' | 'repeat' | 'comma'
  • 具備 encodeURIComponent(key)
  • 具備 encodeURIComponent(value)
  • 可以處理 value 為對象的情況
  • 重複的 key 的解析 ?a=1&a=a { a: ["1","a"]}

自己實現格式化和解析(僅限於 value 是基本類型)

拋出結論:

  • 需要手動去掉 location.search?
  • 具備 encodeURIComponent(key)
  • 具備 encodeURIComponent(value)
  • 無法處理 value 為對象的情況( 被處理成 '[object Object]')

方法一: split + reduce

格式化
const stringify  = (query) => {
    return Object.keys(query).reduce((pre,key) => {
        return pre + `${encodeURIComponent(key)}=${encodeURIComponent(query[key])}&`
    },'').slice(0,-1)
}

調用:console.log(stringify(query))
返回 :a=a&b=1&c=1%2C2%2C3%2C%5Bobject%20Object%5D&d=%5Bobject%20Object%5D&e=https%3A%2F%2Fwww.baidu.com%3Fa%3D1%26b%3D1%23tag

解析
const parse = (queryStr) => {
    const str = queryStr.replace(/^\?/,'')
    return queryStr.split('&').reduce((pre,key) => {
        const [k,v] = key.split('=')
        pre[decodeURIComponent(k)] = decodeURIComponent(v)
        return pre
    },{})
}

調用上面 stringigyparse(str)
返回:

{ a: 'a',
  b: '1',
  c: '1,2,3,[object Object]',
  d: '[object Object]',
  e: 'https://www.baidu.com?a=1&b=1#tag'
 }

方法二 URL + URLSearchParams

URL: https://developer.mozilla.org/zh-CN/docs/Web/API/URL

URLSearchParams:https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchPar...

格式化
const url = new URL("https://example.com/?a=hello&b=world");

console.log(url.href);
// https://example.com/?a=hello&b=world

console.log(url.origin);
// https://example.com

const add_params = {
  c: "a",
  d: new String(2),
  e: false.toString(),
};

const new_params = new URLSearchParams([
  ...Array.from(url.searchParams.entries()), // [["a","hello"],["b","world"]]
  ...Object.entries(add_params), // [["c","a"],["d","2"],["e","false"]]
]).toString();
console.log(new_params);
// a=hello&b=world&c=a&d=2&e=false

const new_url = new URL(`${url.origin}${url.pathname}?${new_params}`);

console.log(new_url.href);
// https://example.com/?a=hello&b=world&c=a&d=2&e=false

// Here it is as a function that accepts (URL, Record<string, string>)
const addSearchParams = (url, params = {}) =>
  new URL(
    `${url.origin}${url.pathname}?${new URLSearchParams([
      ...Array.from(url.searchParams.entries()),
      ...Object.entries(params),
    ])}`,
  );

使用上面數據:

 const url = new URL("https://example.com/?a1=hello&b1=world");
  console.log("url==>", url);
  const addSearchParams = (url, params = {}) =>
    new URL(
      `${url.origin}${url.pathname}?${new URLSearchParams([
        ...Array.from(url.searchParams.entries()),
        ...Object.entries(params)
      ])}`
    );

  console.log("return url==>", addSearchParams(url, query).toString());
  

返回結果:`
https://example.com/?a1=hello&1b=world&a=a&b=1&c=1%2C2%2C3%2C... `

解析
const { searchParams } = new URL(url);
const result = {}
for(let [key, value] of searchParams){
      result[key] = value;
    }
    return result;
}

parse 之後:

{ a1: 'hello',
  '1b': 'world',
  a: 'a',
  b: '1',
  c: '1,2,3,[object Object]',
  d: '[object Object]',
  e: 'https://www.baidu.com?a=1&b=1#tag',
  'a?.b': 'a_b' }

總結

  • URLURLSearchParams 為我們實現 URL 參數格式化和解析提供了新的思路
  • 總體來看推薦使用 qs 這個庫來實現,它的支持能力最強
user avatar cyzf 頭像 Leesz 頭像 nihaojob 頭像 leexiaohui1997 頭像 huichangkudelingdai 頭像 guixiangyyds 頭像 wmbuke 頭像 bugDiDiDi 頭像 xw-01 頭像 geeklab 頭像 Poetwithapistol 頭像 hea1066 頭像
點贊 54 用戶, 點贊了這篇動態!
點贊

Add a new 評論

Some HTML is okay.