【问题标题】:Parse query string in JavaScript [duplicate]在 JavaScript 中解析查询字符串 [重复]
【发布时间】:2011-01-06 15:03:38
【问题描述】:

我需要解析查询字符串www.mysite.com/default.aspx?dest=aboutus.aspx。 如何在 JavaScript 中获取 dest 变量?

【问题讨论】:

标签: javascript parsing query-string


【解决方案1】:

这是在 JavaScript 中解析查询字符串的一种快速简便的方法:

function getQueryVariable(variable) {
    var query = window.location.search.substring(1);
    var vars = query.split('&');
    for (var i = 0; i < vars.length; i++) {
        var pair = vars[i].split('=');
        if (decodeURIComponent(pair[0]) == variable) {
            return decodeURIComponent(pair[1]);
        }
    }
    console.log('Query variable %s not found', variable);
}

现在向 page.html?x=Hello 发出请求:

console.log(getQueryVariable('x'));

【讨论】:

  • 您还应该解码任何经过百分比编码的特殊字符
  • 简单,但如果您需要获取多个查询值,速度不是很快。我认为更好的抽象是从查询字符串中返回一个包含所有名称值对的 JS 对象
  • 另外,split("=") 不够好,你可以有一个“name=value”对,其中 value 包含一个非编码的 '='。解决方案是执行 indexOf('=') 来查找第一个 '=',以及之前和之后的子字符串。
  • ?this=1&amp;this=2&amp;this=3怎么样
  • @gotofritz,我认为这不会做同样的事情: "a=b=c".split("=", 2) 给你 [ 'a', 'b' ],你想要的是 ['a', 'b=c']
【解决方案2】:
function parseQuery(queryString) {
    var query = {};
    var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
    for (var i = 0; i < pairs.length; i++) {
        var pair = pairs[i].split('=');
        query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
    }
    return query;
}

hello=1&amp;another=2 之类的查询字符串转换为对象{hello: 1, another: 2}。从那里,很容易提取你需要的变量。

也就是说,它不处理诸如"hello=1&amp;hello=2&amp;hello=3" 之类的数组情况。为此,您必须在添加之前检查您创建的对象的属性是否存在,并将其值转换为数组,推送任何额外的位。

【讨论】:

  • 如果 b 是一个元素的数组,那么这个函数将失败。前任。 somesite.com/?varrible1=data&varrible2= 前。 somesite.com/?varrible1=data&varrible
  • 修复了错误并更新了代码。抱歉,我想在这里大声喊一下:“Javascript,为什么我们必须手动执行此操作?犯错误!JS 不是要在浏览器中工作并帮助人们进行 Web 开发吗?
  • 这行得通,只需添加一个 if 语句来验证 pair[0]!=""
  • 可以缩短一点:queryString.replace(/^\?/, '').split('&amp;') 感谢您的解决方案 :)
【解决方案3】:

您还可以使用Rodney Rehm 提供的出色的URI.js 库。方法如下:-

var qs = URI('www.mysite.com/default.aspx?dest=aboutus.aspx').query(true); // == { dest : 'aboutus.aspx' }
    alert(qs.dest); // == aboutus.aspx

并解析当前页面的查询字符串:-

var $_GET = URI(document.URL).query(true); // ala PHP
    alert($_GET['dest']); // == aboutus.aspx 

【讨论】:

  • .query(true) 部分的参数有什么作用?是否将查询作为键值对象而不是查询字符串返回?
  • 很酷,但需要 3rd 方库的解决方案并不理想。我有点惊讶这个解决方案得到了如此多的支持。无意冒犯@SalmanPK
  • @Madbreaks 但是自定义、重新发明轮子、未经实战测试且功能非常有限的解决方案是什么?有趣;)
  • 一个好的原生解决方案(几乎)总是比一个需要第三方工具的好解决方案好,这就是我的意思。
  • 即便如此,知道这样的工具存在总是很高兴。事实上,我确切地知道如何手动解析查询,但我更喜欢谷歌寻找更好的解决方案,这就是我首先来到这里的原因。 ;)
【解决方案4】:

我也是! http://jsfiddle.net/drzaus/8EE8k/

(注意:没有花哨的嵌套或重复检查)

deparam = (function(d,x,params,p,i,j) {
return function (qs) {
    // start bucket; can't cheat by setting it in scope declaration or it overwrites
    params = {};
    // remove preceding non-querystring, correct spaces, and split
    qs = qs.substring(qs.indexOf('?')+1).replace(x,' ').split('&');
    // march and parse
    for (i = qs.length; i > 0;) {
        p = qs[--i];
        // allow equals in value
        j = p.indexOf('=');
        // what if no val?
        if(j === -1) params[d(p)] = undefined;
        else params[d(p.substring(0,j))] = d(p.substring(j+1));
    }

    return params;
};//--  fn  deparam
})(decodeURIComponent, /\+/g);

和测试:

var tests = {};
tests["simple params"] = "ID=2&first=1&second=b";
tests["full url"] = "http://blah.com/?third=c&fourth=d&fifth=e";
tests['just ?'] = '?animal=bear&fruit=apple&building=Empire State Building&spaces=these+are+pluses';
tests['with equals'] = 'foo=bar&baz=quux&equals=with=extra=equals&grault=garply';
tests['no value'] = 'foo=bar&baz=&qux=quux';
tests['value omit'] = 'foo=bar&baz&qux=quux';

var $output = document.getElementById('output');
function output(msg) {
    msg = Array.prototype.slice.call(arguments, 0).join("\n");
    if($output) $output.innerHTML += "\n" + msg + "\n";
    else console.log(msg);
}
var results = {}; // save results, so we can confirm we're not incorrectly referencing
$.each(tests, function(msg, test) {
    var q = deparam(test);
    results[msg] = q;
    output(msg, test, JSON.stringify(q), $.param(q));
    output('-------------------');
});

output('=== confirming results non-overwrite ===');
$.each(results, function(msg, result) {
    output(msg, JSON.stringify(result));
    output('-------------------');
});

结果:

simple params
ID=2&first=1&second=b
{"second":"b","first":"1","ID":"2"}
second=b&first=1&ID=2
-------------------
full url
http://blah.com/?third=c&fourth=d&fifth=e
{"fifth":"e","fourth":"d","third":"c"}
fifth=e&fourth=d&third=c
-------------------
just ?
?animal=bear&fruit=apple&building=Empire State Building&spaces=these+are+pluses
{"spaces":"these are pluses","building":"Empire State Building","fruit":"apple","animal":"bear"}
spaces=these%20are%20pluses&building=Empire%20State%20Building&fruit=apple&animal=bear
-------------------
with equals
foo=bar&baz=quux&equals=with=extra=equals&grault=garply
{"grault":"garply","equals":"with=extra=equals","baz":"quux","foo":"bar"}
grault=garply&equals=with%3Dextra%3Dequals&baz=quux&foo=bar
-------------------
no value
foo=bar&baz=&qux=quux
{"qux":"quux","baz":"","foo":"bar"}
qux=quux&baz=&foo=bar
-------------------
value omit
foo=bar&baz&qux=quux
{"qux":"quux","foo":"bar"}   <-- it's there, i swear!
qux=quux&baz=&foo=bar        <-- ...see, jQuery found it
-------------------

【讨论】:

  • 只是想保持简单
  • 如果查询字符串中的变量之一包含=(等号)符号怎么办
  • 如果任何查询字符串值没有等号则失败,例如:'?val1=1&amp;val2&amp;val3=4',因为在 '=' 上的拆分会导致 pair[1] == null,而 decodeURIComponent(null) 返回字符串 @987654329 @ 而不是值 null。最好使用d(pair[1] || '')
  • @drzaus 我使用了你的代码,但我需要复制参数来解析为数组。如果有人有同样的需求,-jsfiddle.net/sergiyok/yywhxsqz
  • 那里,7 年多之后(几乎)每个人都快乐吗?
【解决方案5】:

这是我的版本,大致基于上面 Braceyard 的版本,但解析为“字典”并支持不带“=”的搜索参数。在我的 JQuery $(document).ready() 函数中使用它。参数作为键/值对存储在 argsParsed 中,您可能希望将其保存在某处...

'use strict';

function parseQuery(search) {

    var args = search.substring(1).split('&');

    var argsParsed = {};

    var i, arg, kvp, key, value;

    for (i=0; i < args.length; i++) {

        arg = args[i];

        if (-1 === arg.indexOf('=')) {

            argsParsed[decodeURIComponent(arg).trim()] = true;
        }
        else {

            kvp = arg.split('=');

            key = decodeURIComponent(kvp[0]).trim();

            value = decodeURIComponent(kvp[1]).trim();

            argsParsed[key] = value;
        }
    }

    return argsParsed;
}

parseQuery(document.location.search);

【讨论】:

  • 是否有理由使用 unescape() 而不是 decodeURI()?
  • 我会添加 if(args[i].length){ 作为循环的第一行,以避免 argsParsed 中出现空键。
  • @ghigo 是的,检查零长度密钥是个好主意,也许在修剪之后。没有理由使用 unescape(),我不记得我从哪里复制的 ;-)
  • 警告:不推荐使用 unescape。见:developer.mozilla.org/en-US/docs/JavaScript/Guide/…
  • 不要使用这段代码,这是错误的。修剪会修改数据,使用 unescape 代替 decodeURIComponent 并且在错误的地方调用它(名称和值应该单独解析,而不是作为 name=value 字符串的一部分)。它还泄漏全局变量并使用“==”来比较值。
【解决方案6】:

从我的评论到@bobby 发布的答案,这是我将使用的代码:

    function parseQuery(str)
        {
        if(typeof str != "string" || str.length == 0) return {};
        var s = str.split("&");
        var s_length = s.length;
        var bit, query = {}, first, second;
        for(var i = 0; i < s_length; i++)
            {
            bit = s[i].split("=");
            first = decodeURIComponent(bit[0]);
            if(first.length == 0) continue;
            second = decodeURIComponent(bit[1]);
            if(typeof query[first] == "undefined") query[first] = second;
            else if(query[first] instanceof Array) query[first].push(second);
            else query[first] = [query[first], second]; 
            }
        return query;
        }

此代码接受提供的查询字符串(作为'str')并返回一个对象。字符串在 & 的所有出现处被拆分,从而产生一个数组。然后遍历数组,其中的每个项目都用“=”分割。这会产生子数组,其中第 0 个元素是参数,第一个元素是值(如果没有 = 符号,则为未定义)。这些映射到对象属性,例如字符串“hello=1&another=2&something”变成:

{
hello: "1",
another: "2",
something: undefined
}

此外,此代码注意到重复出现,例如“hello=1&hello=2”,并将结果转换为数组,例如:

{
hello: ["1", "2"]
}

您还会注意到它处理不使用 = 符号的情况。如果在 & 符号后面紧跟等号,它也会忽略。

对于原始问题来说有点矫枉过正,但如果您需要在 javascript 中使用查询字符串,这是一个可重用的解决方案 :)

【讨论】:

    【解决方案7】:

    如果您知道您将只有一个查询字符串变量,您可以简单地这样做:

    var dest = location.search.replace(/^.*?\=/, '');
    

    【讨论】:

    • 不错。我会添加它,以便正确编码: var dest = unescape(location.search.replace(/^.*\=/, '')).replace(/\+/g, " ");
    • 你能修改它以说明查询字符串上的潜在锚点吗?
    • 正则表达式应该在* 之后有一个?。照原样,查询字符串 ?dest=foo=bar 将失败。
    • 你是正确的@st-boost,我纠正了这个。谢谢!
    【解决方案8】:

    以下函数将用正则表达式解析搜索字符串,缓存结果并返回请求变量的值:

    window.getSearch = function(variable) {
      var parsedSearch;
      parsedSearch = window.parsedSearch || (function() {
        var match, re, ret;
        re = /\??(.*?)=([^\&]*)&?/gi;
        ret = {};
        while (match = re.exec(document.location.search)) {
          ret[match[1]] = match[2];
        }
        return window.parsedSearch = ret;
      })();
      return parsedSearch[variable];
    };
    

    您可以在没有任何参数的情况下调用它一次并使用window.parsedSearch 对象,或者随后调用getSearch。 我还没有完全测试过,正则表达式可能还需要一些调整......

    【讨论】:

    • 似乎是“我有问题。我将使用一些正则表达式来解决它。现在我有两个问题。”告诉我这比@Braveyard 的字符串解析方法好多少。
    • 就像我写的那样,它将被解析一次并缓存在一个对象中。 @Braveyard 的代码将在您每次调用该函数时解析整个哈希,并遍历所有可用变量,直到找到正确的变量。
    • @cori 正则表达式与拆分字符串只是我猜的口味问题......
    • @cori 更好,因为它具有挑战性......虽然这是一种更令人沮丧的程序员方法......
    【解决方案9】:

    这个怎么样?

    function getQueryVar(varName){
        // Grab and unescape the query string - appending an '&' keeps the RegExp simple
        // for the sake of this example.
        var queryStr = unescape(window.location.search) + '&';
    
        // Dynamic replacement RegExp
        var regex = new RegExp('.*?[&\\?]' + varName + '=(.*?)&.*');
    
        // Apply RegExp to the query string
        var val = queryStr.replace(regex, "$1");
    
        // If the string is the same, we didn't find a match - return false
        return val == queryStr ? false : val;
    }
    

    ..然后只需调用它:

    alert('Var "dest" = ' + getQueryVar('dest'));
    

    干杯

    【讨论】:

    • 投反对票者,希望得到解释......
    • 你应该先在 & 处拆分,然后在 unescape 处拆分。否则,如果值包含编码的 & 或 =,则此代码肯定会失败,特别是如果它重复部分关键字
    【解决方案10】:

    我想要一个简单的函数,它将 URL 作为输入并返回查询参数的映射。 如果我要改进这个功能,我会支持 URL 中的数组数据和/或嵌套变量的标准。

    这应该适用于 jQuery.param( qparams ) 函数。

    function getQueryParams(url){
        var qparams = {},
            parts = (url||'').split('?'),
            qparts, qpart,
            i=0;
    
        if(parts.length <= 1 ){
            return qparams;
        }else{
            qparts = parts[1].split('&');
            for(i in qparts){
    
                qpart = qparts[i].split('=');
                qparams[decodeURIComponent(qpart[0])] = 
                               decodeURIComponent(qpart[1] || '');
            }
        }
    
        return qparams;
    };
    

    【讨论】:

    • if(parts.length &lt;= 1 ){ 造成了一些混乱......
    • ?a=b=c 时中断
    • @Spongman 在什么情况下使用?a=b=c
    • @ShannonMatthews 如果要将字符串“b=c”传递给参数“a”。或包含“=”字符的任何值。上面的代码假定该值不包含'='。
    • 谢谢@Spongman。
    【解决方案11】:

    我想在页面上的 DOM 元素中获取 特定 链接,将这些用户发送到计时器上的重定向页面,然后将它们传递给点击的原始页面网址。这就是我使用包含上述方法之一的常规 javascript 来实现的。

    带有链接的页面: 头部

      function replaceLinks() {   
    var content = document.getElementById('mainContent');
                var nodes = content.getElementsByTagName('a');
            for (var i = 0; i < document.getElementsByTagName('a').length; i++) {
                {
                    href = nodes[i].href;
                    if (href.indexOf("thisurl.com") != -1) {
    
                        nodes[i].href="http://www.thisurl.com/redirect.aspx" + "?url=" + nodes[i];
                        nodes[i].target="_blank";
    
                    }
                }
        }
    }
    

    身体

    <body onload="replaceLinks()">
    

    重定向页面

       function getQueryVariable(variable) {
            var query = window.location.search.substring(1);
            var vars = query.split('&');
            for (var i = 0; i < vars.length; i++) {
                var pair = vars[i].split('=');
                if (decodeURIComponent(pair[0]) == variable) {
                    return decodeURIComponent(pair[1]);
                }
            }
            console.log('Query variable %s not found', variable);
        }
        function delayer(){
            window.location = getQueryVariable('url')
        }
    

    身体

    <body onload="setTimeout('delayer()', 1000)">
    

    【讨论】:

    • 欢迎来到 Stack Overflow。这是一个问题吗?
    • 不,我认为分享一个运行中的解析器示例可能会很有用。
    猜你喜欢
    • 1970-01-01
    • 2020-01-07
    • 2020-05-13
    • 1970-01-01
    • 2018-09-13
    • 2014-12-21
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    相关资源
    最近更新 更多