通常在实际项目中,无论操作数据
、或是dom
,我们需要熟悉一些浏览器
的API
,或是js
原生给我们扩展的API
,我们熟悉了这些API
,某种意义上来说,一些高效的API
和方法
常常会解惑你项目中遇到的很多疑难杂症。
本文只作一些笔者项目中关于URL
常用到的API
,希望在你项目中能带来一点思考和帮助。
正文开始...
location 对象
控制台下,window.location
获取浏览器地址 URL 相关信息
// window.location
/*
https://www.baidu.com/s?wd=Reflect.%20defineProperty&rsv_spt=1#123
*/
const { href, origin, host, port, protocol, pathname, hash, search } = window.location;
console.log(href); // 获取整个URL xxx
console.log(origin); // 协议+域名+端口 https://www.baidu.com
console.log(host); // 主机名+端口号(http或者https会省略端口号) www.baidu.com
console.log(port); // '' http默认端口80 https默认端口443
console.log(protocol); // 协议 https:
console.log(pathname); // 除了域名的路由地址路径
console.log(hash); // 路径带#的参数
console.log(search); // 地址?后面所有参数
在location.search
、location.hash
、location.origin
、location.href
是通常项目中几个比较高频的获取当前地址的一些参数方法,不过注意只有location.origin
这个是只读的,其他API
都是可读可写
URL
在js
中创建一个地址,使用场景,举个栗子,我们用URL
模拟当前页面的地址
const url = new URL('https://www.baidu.com/s?wd=Reflect.%20defineProperty&rsv_spt=1#123');
console.log(url.search); // ?wd=Reflect.%20defineProperty&rsv_spt=1
console.log(url.hash); // #123
console.log(url.origin); // https://www.baidu.com
console.log(url.href); // 'https://www.baidu.com/s?wd=Reflect.%20defineProperty&rsv_spt=1#123'
URL
这个原生构造的地址中属性与location
获取地址上的通用属性都基本一样。唯一的区别是,location
多了replace
与reload
方法,URL
除了拥有location
的通用属性,没有replace
与reload
方法,但是他具备一个获取参数的一个searchParams
API
...
console.log(url.searchParams);
// { 'wd' => 'Reflect. defineProperty', 'rsv_spt' => '1' }
console.log(url.searchParams.toString());
// wd=Reflect.+defineProperty&rsv_spt=1
searchParams
快速获取URL
中携带参数的方法,这个在URL
构建的地址中非常方便。比如现在有一个需求,我需要将一个地址的参数转换成key
与value
的键值对。
以前我们的做法是这样的
function formateQueryUrl() {
const { search } = window.location;
// 以?分割,获取url上的真正的参数
const [, searchStr] = search.split('?');
// 以&分割前后参数
const arr = searchStr.split('&');
const ret = {};
arr.forEach((v) => {
const [key, val] = v.split('=');
ret[key] = val;
});
return ret;
}
现在我们可以更高效的利用URL
的searchParams
// 与上面formateQueryUrl方法等价
function eazyFormateQueryUrl() {
const url = new URL(window.location);
return Object.fromEntries(url.searchParams.entries());
}
// 如果当前浏览器地址 https://www.badu.com?a=1&b=2
// {a:1,b:2}
这个eazyFormateQueryUrl
方法是不是很简单,两行代码就搞定了格式化url
中的参数,并且将一串字符串参数轻松的转换成了对象
注意上面的方法我们使用了Object.fromEntries
与url.searchParams.entries()
,其实url.searchParams
的构造函数就是URLSearchParams
,而URLSearchParams
是一个具有可迭代器
功能的 API,所以你可以for...of
或者entries
操作。
同时我们注意fromEntries
,我们看下这个API
,通常我们不常用,一般我们都是entries
操作得多,但是实际上fromEntries
就是还原对象的entries
操作,这里我们就是利用了这一点。
举个栗子
const ret = { name: 'Maic', public: 'Web技术学苑' };
const arr = Object.entries(ret);
console.log(arr);
// [['name', 'Maic'], ['public', 'Web技术学苑']]
如果你想将arr
还原成以前的对象,那么你肯定想到循环的做法,像下面这样
...
const target = {};
arr.forEach(item => {
const [key, val] = item;
target[key] = val;
});
console.log(target);
// {name: 'Maic', public: 'Web技术学苑'}
其实不用循环,原生 Object 提供了一个API
,它可以将entries
数据还原成以前的。那么我们可以简单实现
const ret = { name: 'Maic', public: 'Web技术学苑' };
const arr = Object.entries(ret);
/* const target = {};
arr.forEach(item => {
const [key, val] = item;
target[key] = val;
});
*/
// 与下面等价
const target = Object.fromEntries(arr);
// {name: 'Maic', public: 'Web技术学苑'}
正因为如此,我们利用了fromEntries
的这点特性,巧妙的将原数据进行转对象了。
对于URL
,我们还需要可以动态的添加路径,比如下面一个栗子
function locationByNamePath(path) {
const { origin } = window.location;
const url = new URL(path, origin);
window.location.href = url.href;
}
locationByNamePath('/index.html');
// https://www.baidu.com/index.html
locationByNamePath('/about.html');
// https://www.baidu.com/about.html
URLSearchParams
这个API
是一个原生的构造函数,可以获取地址?
后面的参数信息
举个栗子
var urlSearch = new URLSearchParams(window.location.search);
console.log(`${urlSearch}`);
// 打开百度,在控制台随便输入关键字搜索,控制台复制该断代码,就可以看到
URLSearchParams
传入字符串
const search = new URLSearchParams('a=1&b=2&c=3');
console.log(search.toString()); // a=1&b=2&c=3
等价于
const search = new URLSearchParams(window.location.search);
console.log(search.toString()); // a=1&b=2&c=3
URLSearchParams
传入数组,将一个对象转换成url
参数,通常在ajax
get 请求拼接参数时,可能很有用
const obj = { a: 1, b: 2, c: 3 };
const search2 = new URLSearchParams(Object.entries(obj));
console.log(search2.toString());
//a=1&b=2&c=3
$.ajax({
url: `xxxx?${search2}`,
methods: 'get'
});
当我们使用fetch
原生api
请求时,new URLSearchParams
可以作为body
参数
const params = {
name: 'maic',
password: '123456'
};
fetch('https://baidu.com', {
methods: 'POST',
body: new URLSearchParams(params)
});
我们知道URLSearchParams
具有可迭代器属性的特征,因此它像Map
、Set
一样具有增删查改
的特性
查
get 获取参数值
const obj = { a: 1, b: 2, c: 3 };
const search2 = new URLSearchParams(Object.entries(obj));
console.log(search2.get('a')); // 1
console.log(search2.get('b')); // 2
console.log(search2.get('c')); // 3
增
append,添加某个参数
...
search2.append('d', 'hello')
// a=1&b=2&c=3&d=hello
删
delete 删除某个参数
...
search2.delete('a');
console.log(search2.toString());
//b=2&c=3
改
set 修改参数
const obj = { a: 1, b: 2, c: 3 };
const search2 = new URLSearchParams(Object.entries(obj));
search2.set('a', '666');
console.log(`${search2}`);
// a=666&b=2&c=3&d=hello
是否存在
has 判断有没有key
...
console.log(search2.has('a')); // true
获取URLSearchParams
所有的key
或者value
new URLSearchParams({a:1,b:2,c:3}).keys()
,new URLSearchParams({a:1,b:2,c:3}).values()
const obj = { a: 1, b: 2, c: 3 };
const search2 = new URLSearchParams(Object.entries(obj));
const keys = Array.from(search2.keys());
console.log(keys);
// ['a', 'b', 'c']
const values = Array.from(search2.values());
// ['1', '2', '3']
对于URLSearchParams
可以传字符串
,可以是对象
或是数组
,当我们获取URLSearchParams
的 key,直接调用xxx.keys()
或者是xxx.values()
,不过这样取出的值是一个迭代器,还需要用Array.from
中转一下。
还原URLSearchParams
参数
...
Object.fromEntries(search2.entries());
// {a:1,b:2,c:3}
总结
location
常用获取hostname
、origin
、search
、hash
等URL
创建 url,并且拥有searchParams
获取 url 中的?
后面的参数利用
URLSearchParams
高效格式化url
参数,两行代码实现了格式化?
参数URLSearchParams
这个API
可以直接获取 url 参数,并提供增删查改
[append、delete、get、set、has]方法