Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

URLSearchParams初体验 #31

Open
lengxing opened this issue May 7, 2019 · 0 comments
Open

URLSearchParams初体验 #31

lengxing opened this issue May 7, 2019 · 0 comments
Assignees

Comments

@lengxing
Copy link
Owner

lengxing commented May 7, 2019

在之前发的工具方法文章的的留言中有人就关于验证网址的操作时可以使用URL对象,之后有人提到了URLSearchParams这个URL对象接口。由于之前没有接触过,所以搜索了一下具体的用处,发现这个接口的功能很实用,特此整理分享一下。

URLSearchParams是什么

URLSearchParams 接口定义了一些实用的方法来处理 URL 的查询字符串。参照

从而我们可以知道,它是用来处理URL相关的。那具体都有哪些功能呢?

接口方法

首先,我们调用new URLSearchParams()会返回一个 URLSearchParams 对象实例。在这个实例下面我们可以调用以下方法:

  • append(name, value):插入一个指定的键/值对作为新的搜索参数。
    其中name是需要插入搜索参数的键名,value是需要插入搜索参数的对应值。

    let url = new URL('https://example.com?foo=1&bar=2');
    let params = new URLSearchParams(url.search.slice(1));
    
    //添加第二个foo搜索参数。
    params.append('foo', 4);
    params.toString();
    // 'foo=1&bar=2&foo=4'
    
  • delete(name):从搜索参数列表里删除指定的搜索参数及其对应的值。
    name是需要删除的键值名称。

    let url = new URL('https://example.com?foo=1&bar=2');
    let params = new URLSearchParams(url.search.slice(1));
    
    //添加第二个foo搜索参数。
    params.delete('foo');
    params.toString();
    // 'bar=2'
    
  • entries():返回一个iterator可以遍历所有键/值对的对象。

    // 创建一个测试用 URLSearchParams 对象
    let searchParams = new URLSearchParams("key1=value1&key2=value2");
    
    // 显示键/值对
    for(var pair of searchParams.entries()) {
       console.log(pair[0]+ ', '+ pair[1]); 
    }
    
    // key1, value1
    // key2, value2
    
  • get(name):获取指定搜索参数的第一个值。
    name是将要返回的参数的键名。返回一个USVString;如果没有,则返回null
    如果一个页面的URL是 https://example.com/?name=Jonathan&age=18 ,你可以这样解析参数nameage:

    let params = new URLSearchParams(document.location.search.substring(1));
    let name = params.get("name"); // is the string "Jonathan"
    let age = parseInt(params.get("age"), 10); // is the number 18
    
    // 查找一个不存在的键名则返回 null:
    let address = params.get("address"); // null
    
  • getAll(name):获取指定搜索参数的所有值,返回是一个数组。
    name是返回的参数的名称。

    let url = new URL('https://example.com?foo=1&bar=2'); 
    let params = new URLSearchParams(url.search.slice(1)); 
    
    //为foo参数添加第二个值 
    params.append('foo', 4);
    
    console.log(params.getAll('foo'))' //输出 ["1","4"].
    
  • has(name):返回 Boolean 判断是否存在此搜索参数。
    name 是我们要查询的参数的键名。

    let url = new URL('https://example.com?foo=1&bar=2');
    let params = new URLSearchParams(url.search.slice(1));
    
    params.has('bar') === true; //true
    
  • keys():返回iterator 此对象包含了键/值对的所有键名。

    // 建立一个测试用URLSearchParams对象
    let searchParams = new URLSearchParams("key1=value1&key2=value2"); 
    
    // 输出键值对
    for(var key of searchParams.keys()) { 
      console.log(key); 
    }
    
    // key1
    // key2
    
  • set(name, value):设置一个搜索参数的新值,假如原来有多个值将删除其他所有的值
    其中name是需要插入修改参数的键名,value是需要插入搜索参数的新值。

    let url = new URL('https://example.com?foo=1&bar=2');
    let params = new URLSearchParams(url.search.slice(1));
    
    //Add a third parameter.
    params.set('baz', 3);
    
  • sort(): 按键名排序。

    // Create a test URLSearchParams object 
    let searchParams = new URLSearchParams("c=4&a=2&b=3&a=1"); 
    
    // Sort the key/value pairs
    searchParams.sort();
    
    // Display the sorted query string
    console.log(searchParams.toString());
    
    // a=2&a=1&b=3&c=4
    
  • toString():返回搜索参数组成的字符串,可直接使用在URL上。

    let url = new URL('https://example.com?foo=1&bar=2');
    let params = new URLSearchParams(url.search.slice(1));
    
    //Add a second foo parameter.
    params.append('foo', 4);
    console.log(params.toString());
    //Prints 'foo=1&bar=2&foo=4'.
    
  • values():返回iterator 此对象包含了键/值对的所有值。

    // 创建一个测试用URLSearchParams对象
    let searchParams = new URLSearchParams("key1=value1&key2=value2");
    
    // 输出值
    for(var value of searchParams.values()) {
      console.log(value);
    }
    

上面就是针对其所有的接口方法进行的一个梳理。然而,感觉好像和我们平时的关联没有很大呢?下面让我们来看几个具体的使用场景。

使用场景

场景一 获取浏览器地址参数

我们之前在获取浏览器地址参数时很多时候是通过对地址进行分割,然后拼接字段对象的方式来做的,类似

function GetRequest() {
  let url = location.search; //获取url中"?"符后的字串
  let theRequest = new Object();
  if (url.indexOf("?") != -1) {
    let str = url.substr(1);
    strs = str.split("&");
    for (let i = 0; i < strs.length; i++) {
      theRequest[strs[i].split("=")[0]] = (strs[i].split("=")[1]);
    }
  }
  return theRequest;
}

但是我们如果使用URLSearchParams时就不用这么繁琐了

const params = new URLSearchParams(location.search)
params.get(key)

使用URLSearchParams处理axios发送的数据

在我们使用axiosfetch来替换之前的ajax进行数据请求时,我们会遇到数据格式不一致的问题。

axios({
    method: 'post',
    url: '/test',
    data: {
        name: 'li lei',
        age: 18
    }
})

上面的调用方法和我们使用ajax时非常相似,我们可能也会自然而然的这样来写,但是我们会发现,其默认的数据格式是有差别的:

axios数据格式:
axios数据格式

ajax数据格式:
ajax数据格式

是的,多了一层包裹,这样和我们后端的对接就出现问题了。哪怕是手动去修改ContentType为application/x-www-form-urlencoded仍然没有解决。3

axios数据格式修改后

那么URLSearchParams能如何解决呢

let params = new URLSearchParams();
params.append('name', 'li lei');
params.append('age', 18);

axios({
    method: 'post',
    url: '/test',
    data: params
})

兼容性解决

工具好用,但是不可避免的兼容性并没有那么的理想。那我们该怎么办呢?

工欲善其事,必先利其器

url-search-params-polyfill

这是一个专门为URLSearchParams制作的polyfill库。具体的使用方法大家可以参照库的相关说明。在这主要再强调一下,这个库能够解决浏览器的兼容性问题,但是在使用fetch进行请求调用时,我们仍然需要手动去设置ContentType的值。引用该库中给到的一个实例

function myFetch(url, { headers = {}, body }) {
    headers = headers instanceof Headers ? headers : new Headers(headers);
    
    if (body instanceof URLSearchParams) {
        headers.set('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    }
    
    fetch(url, {
        headers,
        body
    });
}

小结

通过我们对官方接口的说明以及实际场景的使用,详细了解了URLSearchParams的主要功能和使用方法,希望能够在我们以后的开发中起到帮助作用。


参考资料:
URLSearchParams API
使用URLSearchParams处理axios发送的数据

@lengxing lengxing self-assigned this May 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant