是否有一种通过jQuery(或不使用)检索查询字符串值的无插件方法?
如果是,怎么办?如果没有,是否有插件可以这样做?
是否有一种通过jQuery(或不使用)检索查询字符串值的无插件方法?
如果是,怎么办?如果没有,是否有插件可以这样做?
当前回答
可靠地做这件事比一开始想象的要复杂得多。
其他答案中使用的location.search很脆弱,应该避免使用-例如,如果有人搞砸了,并在?查询字符串。在我看来,URL在浏览器中自动转义的方式有很多种,这使得decodeURIComponent非常强制性。许多查询字符串是由用户输入生成的,这意味着对URL内容的假设非常糟糕。包括非常基本的东西,比如每个键都是唯一的,甚至有一个值。
为了解决这个问题,这里提供了一个可配置的API,并提供了健康的防御性编程。请注意,如果您愿意对某些变量进行硬编码,或者如果输入不能包含hasOwnProperty等,则可以将其大小减半。
版本1:返回包含每个参数的名称和值的数据对象。它有效地消除了重复,并始终尊重从左到右找到的第一个。
function getQueryData(url, paramKey, pairKey, missingValue, decode) {
var query, queryStart, fragStart, pairKeyStart, i, len, name, value, result;
if (!url || typeof url !== 'string') {
url = location.href; // more robust than location.search, which is flaky
}
if (!paramKey || typeof paramKey !== 'string') {
paramKey = '&';
}
if (!pairKey || typeof pairKey !== 'string') {
pairKey = '=';
}
// when you do not explicitly tell the API...
if (arguments.length < 5) {
// it will unescape parameter keys and values by default...
decode = true;
}
queryStart = url.indexOf('?');
if (queryStart >= 0) {
// grab everything after the very first ? question mark...
query = url.substring(queryStart + 1);
} else {
// assume the input is already parameter data...
query = url;
}
// remove fragment identifiers...
fragStart = query.indexOf('#');
if (fragStart >= 0) {
// remove everything after the first # hash mark...
query = query.substring(0, fragStart);
}
// make sure at this point we have enough material to do something useful...
if (query.indexOf(paramKey) >= 0 || query.indexOf(pairKey) >= 0) {
// we no longer need the whole query, so get the parameters...
query = query.split(paramKey);
result = {};
// loop through the parameters...
for (i = 0, len = query.length; i < len; i = i + 1) {
pairKeyStart = query[i].indexOf(pairKey);
if (pairKeyStart >= 0) {
name = query[i].substring(0, pairKeyStart);
} else {
name = query[i];
}
// only continue for non-empty names that we have not seen before...
if (name && !Object.prototype.hasOwnProperty.call(result, name)) {
if (decode) {
// unescape characters with special meaning like ? and #
name = decodeURIComponent(name);
}
if (pairKeyStart >= 0) {
value = query[i].substring(pairKeyStart + 1);
if (value) {
if (decode) {
value = decodeURIComponent(value);
}
} else {
value = missingValue;
}
} else {
value = missingValue;
}
result[name] = value;
}
}
return result;
}
}
版本2:返回一个具有两个相同长度数组的数据映射对象,一个用于名称,另一个用于值,每个参数都有一个索引。此格式支持重复名称,并故意不消除重复名称,因为这可能就是您希望使用此格式的原因。
function getQueryData(url, paramKey, pairKey, missingValue, decode) {
var query, queryStart, fragStart, pairKeyStart, i, len, name, value, result;
if (!url || typeof url !== 'string') {
url = location.href; // more robust than location.search, which is flaky
}
if (!paramKey || typeof paramKey !== 'string') {
paramKey = '&';
}
if (!pairKey || typeof pairKey !== 'string') {
pairKey = '=';
}
// when you do not explicitly tell the API...
if (arguments.length < 5) {
// it will unescape parameter keys and values by default...
decode = true;
}
queryStart = url.indexOf('?');
if (queryStart >= 0) {
// grab everything after the very first ? question mark...
query = url.substring(queryStart + 1);
} else {
// assume the input is already parameter data...
query = url;
}
// remove fragment identifiers...
fragStart = query.indexOf('#');
if (fragStart >= 0) {
// remove everything after the first # hash mark...
query = query.substring(0, fragStart);
}
// make sure at this point we have enough material to do something useful...
if (query.indexOf(paramKey) >= 0 || query.indexOf(pairKey) >= 0) {
// we no longer need the whole query, so get the parameters...
query = query.split(paramKey);
result = {
names: [],
values: []
};
// loop through the parameters...
for (i = 0, len = query.length; i < len; i = i + 1) {
pairKeyStart = query[i].indexOf(pairKey);
if (pairKeyStart >= 0) {
name = query[i].substring(0, pairKeyStart);
} else {
name = query[i];
}
// only continue for non-empty names...
if (name) {
if (decode) {
// unescape characters with special meaning like ? and #
name = decodeURIComponent(name);
}
if (pairKeyStart >= 0) {
value = query[i].substring(pairKeyStart + 1);
if (value) {
if (decode) {
value = decodeURIComponent(value);
}
} else {
value = missingValue;
}
} else {
value = missingValue;
}
result.names.push(name);
result.values.push(value);
}
}
return result;
}
}
其他回答
http://someurl.com?key=value&keynovalue&keyemptyvalue=&&keynovalue=nowhasvalue#somehash
常规键/值对(?param=值)不带值的键(?param:无等号或值)键w/空值(?param=:等号,但等号右侧没有值)重复键(?param=1¶m=2)删除空键(?&&:无键或值)
代码:
var queryString=window.location.search | |“”;var keyValPairs=[];var参数={};queryString=queryString.substr(1);if(queryString.length){keyValPairs=queryString.split('&');for(keyValPairs中的pairNum){var key=keyValPairs[pairNum].split('=')[0];如果(!key.length)继续;if(typeof params[key]==“undefined”)params[key]=[];params[key].push(keyValPairs[pairNum].split('=')[1]);}}
如何呼叫:
params['key'];//返回值数组(1..n)
输出:
键[“value”]关键字空值[“”]注释记号[未定义,“nowhasvalue”]
我认为这是实现这一点的准确和简洁的方法(修改自http://css-tricks.com/snippets/javascript/get-url-variables/):
function getQueryVariable(variable) {
var query = window.location.search.substring(1), // Remove the ? from the query string.
vars = query.split("&"); // Split all values by ampersand.
for (var i = 0; i < vars.length; i++) { // Loop through them...
var pair = vars[i].split("="); // Split the name from the value.
if (pair[0] == variable) { // Once the requested value is found...
return ( pair[1] == undefined ) ? null : pair[1]; // Return null if there is no value (no equals sign), otherwise return the value.
}
}
return undefined; // Wasn't found.
}
ES2015(ES6)
getQueryStringParams = query => {
return query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split('&')
.reduce((params, param) => {
let [key, value] = param.split('=');
params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
return params;
}, {}
)
: {}
};
没有jQuery
var qs = (function(a) {
if (a == "") return {};
var b = {};
for (var i = 0; i < a.length; ++i)
{
var p=a[i].split('=', 2);
if (p.length == 1)
b[p[0]] = "";
else
b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
}
return b;
})(window.location.search.substr(1).split('&'));
URL如下?topic=123&name=query+string,将返回以下内容:
qs["topic"]; // 123
qs["name"]; // query string
qs["nothere"]; // undefined (object)
Google方法
撕扯谷歌的代码,我找到了他们使用的方法:getUrlParameters
function (b) {
var c = typeof b === "undefined";
if (a !== h && c) return a;
for (var d = {}, b = b || k[B][vb], e = b[p]("?"), f = b[p]("#"), b = (f === -1 ? b[Ya](e + 1) : [b[Ya](e + 1, f - e - 1), "&", b[Ya](f + 1)][K](""))[z]("&"), e = i.dd ? ia : unescape, f = 0, g = b[w]; f < g; ++f) {
var l = b[f][p]("=");
if (l !== -1) {
var q = b[f][I](0, l),
l = b[f][I](l + 1),
l = l[Ca](/\+/g, " ");
try {
d[q] = e(l)
} catch (A) {}
}
}
c && (a = d);
return d
}
这是模糊的,但可以理解。它无法工作,因为某些变量未定义。
他们开始在url上查找参数?并且还从散列#中。然后,对于每个参数,它们以等号b[f][p](“=”)分割(看起来像indexOf,它们使用字符的位置来获取键/值)。拆分后,他们检查参数是否有值,如果有值,则存储d的值,否则继续。
最后返回对象d,处理转义和+符号。这个对象和我的一样,它有相同的行为。
我的方法作为jQuery插件
(function($) {
$.QueryString = (function(paramsArray) {
let params = {};
for (let i = 0; i < paramsArray.length; ++i)
{
let param = paramsArray[i]
.split('=', 2);
if (param.length !== 2)
continue;
params[param[0]] = decodeURIComponent(param[1].replace(/\+/g, " "));
}
return params;
})(window.location.search.substr(1).split('&'))
})(jQuery);
用法
//Get a param
$.QueryString.param
//-or-
$.QueryString["param"]
//This outputs something like...
//"val"
//Get all params as object
$.QueryString
//This outputs something like...
//Object { param: "val", param2: "val" }
//Set a param (only in the $.QueryString object, doesn't affect the browser's querystring)
$.QueryString.param = "newvalue"
//This doesn't output anything, it just updates the $.QueryString object
//Convert object into string suitable for url a querystring (Requires jQuery)
$.param($.QueryString)
//This outputs something like...
//"param=newvalue¶m2=val"
//Update the url/querystring in the browser's location bar with the $.QueryString object
history.replaceState({}, '', "?" + $.param($.QueryString));
//-or-
history.pushState({}, '', "?" + $.param($.QueryString));
性能测试(针对正则表达式方法的拆分方法)(jsPerf)
准备代码:方法声明
拆分测试代码
var qs = window.GetQueryString(query);
var search = qs["q"];
var value = qs["value"];
var undef = qs["undefinedstring"];
Regex测试代码
var search = window.getParameterByName("q");
var value = window.getParameterByName("value");
var undef = window.getParameterByName("undefinedstring");
在Windows Server 2008 R2/7 x64上的Firefox 4.0 x86中测试
拆分方法:最快144780±2.17%Regex方法:13891±0.85%|90%慢
就获取查询对象的大小而言,最短的表达式似乎是:
var params = {};
location.search.substr(1).replace(/([^&=]*)=([^&]*)&?/g,
function () { params[decodeURIComponent(arguments[1])] = decodeURIComponent(arguments[2]); });
您可以使用A元素将URI从字符串解析到其位置,如组件(例如,去掉#…):
var a = document.createElement('a');
a.href = url;
// Parse a.search.substr(1)... as above
Node.js的源代码中有一个健壮的实现https://github.com/joyent/node/blob/master/lib/querystring.js
TJ的qs也执行嵌套参数解析https://github.com/visionmedia/node-querystring