JavaScript:如何获取和设置URL哈希参数?

41

如何在纯JavaScript中获取和设置URL哈希参数?

例如,我想像这样使用参数:myurl.com/#from=2012-01-05&to=2013-01-01

我想能够获取和设置上述fromto参数。

如果HTML5历史API是最好的方法,我很乐意使用它。


1
对于这种情况,只需使用解析location.search查询的代码location.hash上。 - Bergi
1
@Bergi 谢谢 - 这解释了如何获取参数,但没有说明如何设置它们。我会尝试适应它来设置它们,如果成功的话,我会在这里发布可工作的代码。 - Richard
@cookiemonster 哦,我明白你的意思了:你是说使用查询字符串参数更有意义,例如 ?from=X&to=Y。是的,完全正确,谢谢。 - Richard
如果您想设置这些值,我认为这意味着您想将它们发送到服务器。哈希值不会被发送。 - cookie monster
1
我猜这意味着你想将它们发送到服务器? 为什么要这样假设?我们只是在前端使用这种东西来提供一个可导航的网址,以设置用户界面元素。 - Damien Sawyer
显示剩余5条评论
8个回答

75

如果您想解析哈希URL:

var hash = window.location.hash.substr(1);

var result = hash.split('&').reduce(function (res, item) {
    var parts = item.split('=');
    res[parts[0]] = parts[1];
    return res;
}, {});

这样,如果你有以下内容:

http://example.com/#from=2012-01-05&to=2013-01-01

它会变成:{'from': '2012-01-05', 'to':'2013-01-01'}

如@Dean Stamler在评论中指出,不要忘记空对象:}, {});

现在来设置一个哈希 URL:

window.location.hash = "from=2012-01-05&to=2013-01-01";


@RickS,结果是所有参数的数组。请注意,“from”和“to”是多个参数。请测试一下,它可以很好地处理多个参数。 - crthompson
1
@RickS 如果它不能用于多个参数,很可能是您没有将空对象 {} 作为第二个参数包含在 reduce() 调用中。这是累加器的初始值。 - Dean Stamler
在我看来,让中间结果和最终结果共享同一个变量名有点令人困惑。 - Charlton Provatas

13

您可以使用以下方式设置哈希值:

window.location.hash = "new value";

并且(在新版浏览器中),使用以下方式监听变化:

window.addEventListener("hashchange", function () {
});

如果你需要支持不支持 "hashchange" 的浏览器,你需要使用其他人编写的代码,例如 jQuery 历史记录插件


哪些旧版浏览器不支持 location.hash?(顺便说一下,通常是 window. 而不是 document. - Bergi
location.hash 得到了很好的支持,但是 "hashchange" 却没有。对于旧版本的 IE,你需要使用一个涉及 iframe 的 hack。请参见:http://caniuse.com/#search=hashchange - Halcyon
是的,这正是我所期望的,但是你的措辞“浏览器的新版本支持设置”有些令人困惑。 - Bergi
我只想明确表示,存在兼容性问题。 - Halcyon

12

关于获取参数...这个解决方案怎么样:

var myUrl = new URL(window.location.href.replace(/#/g,"?"));
var param_value = myUrl.searchParams.get("param_name");

祝你好运!


2
只有在URL没有查询参数(并且尚未包含“?”)的情况下,它才能正常工作。因此,例如针对此URL,它将无法正常工作:https://stackoverflow.com/?lala=kuku#bebe=nene - Alexander
@Alexander,您可以这样解决该问题:var myUrl = new URL('a://' + window.location.hash.replace(/^#/g,"?"))a://只是最短的“有效”URL)。 - Lindsay-Needs-Sleep

6

其他答案没有解决这个问题。

我有一个更简单的方法:

将当前的哈希参数复制到一个虚拟URL中作为搜索参数。现在您可以像对待搜索参数一样处理哈希参数,然后再将它们复制回来:

简单的函数

function setOrUpdateHashParameter( hashParameterName, hashParameterValue ) {
    let theURL              = new URL('https://dummy.com');             // create dummy url
    theURL.search           = window.location.hash.substring(1);        // copy current hash-parameters without the '#' AS search-parameters
    theURL.searchParams.set( hashParameterName, hashParameterValue );   // set or update value with the searchParams-API
    window.location.hash    = theURL.searchParams;                      // Write back as hashparameters
}

1
请注意,这在Internet Explorer 11中无法正常工作。https://developer.mozilla.org/en-US/docs/Web/API/URL/URL#Browser_compatibility - Markus

3

多个参数:

原始答案被翻译成“最初的回答”。
const href = window.location.href;
const params = href.split('?')[1];

// Be sure url params exist
if (params && params !== '') {
    const result = params.split('&').reduce(function (res, item) {
        const parts = item.split('=');
        res[parts[0]] = parts[1];
        return res;
    }, {});
}

因此,当 href=https://www.example.net/page.html#/page1?foo=bar&token=123abc 时,result 将计算为 {foo: "bar", token: "123abc"}
这种结构要求URL在参数前有问号?,在变量键和值之间有等号=,并且在每个键/值对之间有一个&

嗨!我正在尝试使用你的代码片段,但它只返回对象中最后一个哈希值。你知道这是为什么吗?我正在使用 window.location.hash,在应用 reduce 之前,我做了这个:decodeURI(window.location.hash).substr(1).split('&') - Olga B
我有一个URL的例子:www.example.com#word=foo&word=bar。这是因为参数使用了相同的键(word)吗? - Olga B
1
@OlgaB 使用这个代码片段时,你需要使用 ? 将参数与其余部分分开。你也可以将 const params 中的 ? 替换为 # - Christopher Chalfant

2
这是我的解决方案。
arr = location.search.replace('?', '').split('&').map(x => x.split('=')).map(x => {
    let keyName = x[0];
    let val = x[1];
    let object = {};
    object[keyName] = val;
    return object;
});

obj = {}

arr.forEach(function(x) {
    let key = Object.keys(x)[0];
    obj[key] = x[key];
});

console.log(obj);

基本上,使用location.search我们可以获取URL的右侧部分,即路径后面的查询参数。location.search还会返回'?'字符,需要替换为空格,然后用'&'进行拆分、映射和'='拆分,以获得类似的数组。
[['term', 'hello'], ['lang', 'es']]

然后,按照您想要的方式组装对象。

arr = "?safe=active&source=hp&ei=c4Q8XcOPFd3F5OUP7e242Ag&q=hola&oq=hola&gs_l=psy-ab.3..0l5j0i131j0l2j0i131j0.1324.1667..1798...1.0..0.264.744.1j3j1......0....1..gws-wiz.....10..35i39.-_FkFlX_Muw&ved=0ahUKEwiDlaTgytXjAhXdIrkGHe02DosQ4dUDCAU&uact=5".replace('?', '').split('&').map(x => x.split('=')).map(x => {
    let keyName = x[0];
    let val = x[1];
    let object = {};
    object[keyName] = val;
    return object;
});

obj = {}

arr.forEach(function(x) {
    let key = Object.keys(x)[0];
    obj[key] = x[key];
});

console.log(obj);


您可能需要提供更多关于您的解决方案所做的事情的信息。 - Rob Rose
1
谢谢@RobRose,我会修改回复的。我的英语不好,抱歉。 - Emanuel Friedrich

2

仅获取:

const startingUrl = 'https://dev59.com/smAg5IYBdhLWcg3wWpxE=XXX&b=YYY'
const myUrl = new URL(startingUrl);
const hash = new URLSearchParams(myUrl.hash.substring(1))
hash.get('state'); // XXX
hash.get('b'); // YYY

enter image description here


1

Maart的回答的基础上,这是一个返回编辑后URL而不是将更改应用于当前窗口的版本。

function setHashParam(url, name, value) {

    // Create URL objects for the url we want to change and a dummy url (requires a polyfill for IE)
    var urlObj = new URL(url);
    var dummyObj = new URL('https://dummy.com');

    // Copy current hash-parameters without the '#' as search-parameters
    dummyObj.search = urlObj.hash.substring(1);

    // Set or update value with the searchParams-API (requires a polyfill for IE)
    dummyObj.searchParams.set(name, value);

    // Write back as hashparameters
    urlObj.hash = dummyObj.searchParams;

    return urlObj.href;
}

请注意,对于这个答案(和Maart的答案)在IE中工作需要URL构造函数和搜索参数API的polyfills。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接