URL参数(也称为查询字符串参数或URL变量)用于通过URL从页面到页面或从客户端到服务器发送少量数据。它们可以包含各种有用的信息,例如搜索查询,链接引荐,产品信息,用户首选项等。
在本文中,我们将向您展示如何使用JavaScript解析和操作URL参数。
本文针对相关性和准确性在2020年进行了更新。
获取URL参数
在现代浏览器中,这要归功于URLSearchParams接口,这变得容易得多。这定义了许多实用程序方法来使用URL的查询字符串。
假设我们的URL是https://example.com/?product=shirt&color=blue&newuser&size=m
,我们可以使用window.location.search
以下命令获取查询字符串:
const queryString = window.location.search;
console.log(queryString);
// ?product=shirt&color=blue&newuser&size=m
然后,我们可以使用解析查询字符串的参数URLSearchParams
:
const urlParams = new URLSearchParams(queryString);
然后,我们对结果调用其任何方法。
例如,URLSearchParams.get()
将返回与给定搜索参数关联的第一个值:
const product = urlParams.get('product')
console.log(product);
// shirt
const color = urlParams.get('color')
console.log(color);
// blue
const newUser = urlParams.get('newuser')
console.log(newUser);
// empty string
其他有用的方法
检查参数是否存在
您可以URLSearchParams.has()
用来检查某个参数是否存在:
console.log(urlParams.has('product'));
// true
console.log(urlParams.has('paymentmethod'));
// false
获取所有参数值
您可以URLSearchParams.getAll()
用来返回与特定参数关联的所有值:
console.log(urlParams.getAll('size'));
// [ 'm' ]
//Programmatically add a second size parameter.
urlParams.append('size', 'xl');
console.log(urlParams.getAll('size'));
// [ 'm', 'xl' ]
遍历参数
URLSearchParams
还提供了一些熟悉的Object
迭代器方法,使您可以迭代其键,值和条目:
const
keys = urlParams.keys(),
values = urlParams.values(),
entries = urlParams.entries();
for (const key of keys) console.log(key);
// product, color, newuser, size
for (const value of values) console.log(value);
// shirt, blue, , m
for(const entry of entries) {
console.log(`${entry[0]}: ${entry[1]}`);
}
// product: shirt
// color: blue
// newuser:
// size: m
浏览器支持
浏览器对的支持URLSearchParams
很好。在撰写本文时,所有主流浏览器均支持该功能。
如果您必须支持Internet Explorer等旧版浏览器,则可以使用polyfill。或者,您可以继续阅读本教程的其余部分,并学习如何进行自己的学习。
滚动您自己的查询字符串解析功能
让我们继续使用上一节中使用的URL:
http://example.com/?product=shirt&color=blue&newuser&size=m
这是一个为所有URL参数提供一个整洁对象的函数:
function getAllUrlParams(url) {
// get query string from url (optional) or window
var queryString = url ? url.split('?')[1] : window.location.search.slice(1);
// we'll store the parameters here
var obj = {};
// if query string exists
if (queryString) {
// stuff after # is not part of query string, so get rid of it
queryString = queryString.split('#')[0];
// split our query string into its component parts
var arr = queryString.split('&');
for (var i = 0; i < arr.length; i++) {
// separate the keys and the values
var a = arr[i].split('=');
// set parameter name and value (use 'true' if empty)
var paramName = a[0];
var paramValue = typeof (a[1]) === 'undefined' ? true : a[1];
// (optional) keep case consistent
paramName = paramName.toLowerCase();
if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();
// if the paramName ends with square brackets, e.g. colors[] or colors[2]
if (paramName.match(/\[(\d+)?\]$/)) {
// create key if it doesn't exist
var key = paramName.replace(/\[(\d+)?\]/, '');
if (!obj[key]) obj[key] = [];
// if it's an indexed array e.g. colors[2]
if (paramName.match(/\[\d+\]$/)) {
// get the index value and add the entry at the appropriate position
var index = /\[(\d+)\]/.exec(paramName)[1];
obj[key][index] = paramValue;
} else {
// otherwise add the value to the end of the array
obj[key].push(paramValue);
}
} else {
// we're dealing with a string
if (!obj[paramName]) {
// if it doesn't exist, create property
obj[paramName] = paramValue;
} else if (obj[paramName] && typeof obj[paramName] === 'string'){
// if property does exist and it's a string, convert it to an array
obj[paramName] = [obj[paramName]];
obj[paramName].push(paramValue);
} else {
// otherwise add the property
obj[paramName].push(paramValue);
}
}
}
}
return obj;
}
您将很快看到它的工作原理,但是首先,这里是一些用法示例:
getAllUrlParams().product; // 'shirt'
getAllUrlParams().color; // 'blue'
getAllUrlParams().newuser; // true
getAllUrlParams().nonexistent; // undefined
getAllUrlParams('http://test.com/?a=abc').a; // 'abc'
这是一个演示供您试用。
使用此功能之前要了解的事项
- 我们的函数假定参数由
&
字符分隔,如W3C规范中所示。但是,通常没有明确定义 URL参数格式,因此您有时可能会看到;
或将其&
作为分隔符。 - 如果参数没有等号或参数没有值,则我们的函数仍然有效。
- 重复参数的值放入数组中。
如果您只想要一个函数,可以将其放入代码中,那么现在就完成了。如果您想了解该功能的工作原理,请继续阅读。
以下部分假定您了解一些JavaScript,包括函数,对象和数组。如果您需要复习,请查看MDN JavaScript参考。
功能如何运作
总体而言,该功能需要一个URL的查询字符串(后部分?
和前#
)和吐出来的是数据在一个整洁的对象。
首先,这一行说,如果我们指定了URL,则在问号后得到所有内容,否则,只需使用窗口的URL:
var queryString = url ? url.split('?')[1] : window.location.search.slice(1);
接下来,我们将创建一个对象来存储我们的参数:
var obj = {};
如果查询字符串存在,我们将开始对其进行解析。首先,我们必须确保从处开始删除该部分#
,因为它不是查询字符串的一部分:
queryString = queryString.split('#')[0];
现在,我们可以将查询字符串分成其组成部分:
var arr = queryString.split('&');
这将为我们提供一个看起来像这样的数组:
['product=shirt', 'color=blue', 'newuser', 'size=m']
接下来,我们将遍历此数组,并将每个项目分为一个键和一个值,我们将很快将它们放入对象中:
var a = arr[i].split('=');
让我们为各个变量分配键和值。如果没有参数值,我们将其设置true
为表示参数名称存在。可以根据您的用例随意更改:
var paramName = a[0];
var paramValue = typeof (a[1]) === 'undefined' ? true : a[1];
(可选)您可以将所有参数名称和值设置为小写。这样,您可以避免有人使用example=TRUE
而不是将流量发送到URL example=true
且脚本中断的情况。(我已经看到这种情况的发生。)但是,如果您的查询字符串需要区分大小写,请随时忽略此部分:
paramName = paramName.toLowerCase();
if (typeof paramValue === 'string') paramValue = paramValue.toLowerCase();
接下来,我们需要处理可以在中接收的各种类型的输入paramName
。这可以是索引数组,非索引数组或常规字符串。
如果它是一个索引数组,我们希望对应paramValue
的数组为一个数组,其值插入正确的位置。如果它是一个非索引数组,我们希望对应paramValue
的数组是一个将元素推到上面的数组。如果它是字符串,那么我们想在该对象上创建一个常规属性,并将其分配paramValue
给它,除非该属性已经存在,在这种情况下,我们希望将现有属性转换为paramValue
数组,然后将传入的paramValue
内容推入该数组。
为了说明这一点,这是一些示例输入,以及我们期望的输出:
getAllUrlParams('http://example.com/?colors[0]=red&colors[2]=green&colors[6]=blue');
// { "colors": [ "red", null, "green", null, null, null, "blue" ] }
getAllUrlParams('http://example.com/?colors[]=red&colors[]=green&colors[]=blue');
// { "colors": [ "red", "green", "blue" ] }
getAllUrlParams('http://example.com/?colors=red&colors=green&colors=blue');
// { "colors": [ "red", "green", "blue" ] }
getAllUrlParams('http://example.com/?product=shirt&color=blue&newuser&size=m');
// { "product": "shirt", "color": "blue", "newuser": true, "size": "m" }
这是实现功能的代码:
if (paramName.match(/\[(\d+)?\]$/)) {
var key = paramName.replace(/\[(\d+)?\]/, '');
if (!obj[key]) obj[key] = [];
if (paramName.match(/\[\d+\]$/)) {
var index = /\[(\d+)\]/.exec(paramName)[1];
obj[key][index] = paramValue;
} else {
obj[key].push(paramValue);
}
} else {
if (!obj[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);
}
}
最后,我们返回带有参数和值的对象。
如果您的网址包含任何编码的特殊字符,例如空格(编码为%20
),则您也可以对其进行解码以获取原始值,如下所示:
// assume a url parameter of test=a%20space
var original = getAllUrlParams().test; // 'a%20space'
var decoded = decodeURIComponent(original); // 'a space'
请注意不要解码已经解码的内容,否则脚本将出错,尤其是涉及百分比时。
无论如何,恭喜!现在您知道了如何获取URL参数,并希望在此过程中学到了其他技巧。
结论
本文中的代码适用于最常见的用例,在这些用例中您将获得URL查询参数。如果您要处理任何边缘情况,例如不常见的分隔符或特殊格式,请确保进行相应的测试和调整。
如果你想要做更多的网址,还有诸如提供特定的库,查询字符串和Medialize URI.js。但是,由于它基本上是字符串操作,因此仅使用纯JavaScript通常很有意义。无论您使用自己的代码还是使用库,请确保检查所有内容并确保其适用于您的用例。