使用JavaScript更改URL参数并指定默认值

243

我有这个 URL:

site.fwx?position=1&archiveid=5000&columns=5&rows=20&sorting=ModifiedTimeAsc

我需要做的是能够更改“rows”URL参数的值为我指定的值,比如说10。如果“rows”不存在,我需要将其添加到URL末尾,并添加我已经指定的值(10)。


13
我很难相信现在已经是2013年了,还没有更好的方法来做到这一点,比如将其构建到核心浏览器库中。 - Tyler Collier
8
@TylerCollier 中2015年至今仍然没有任何进展 :( - Tejas Manohar
4
看起来我们已经接近目标了... https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams/URLSearchParams#浏览器兼容性 - chris
13
@TylerCollier 现在是2021年,我们终于搞定了 :) const myUrl = new URL("http://www.example.com?columns=5&rows=20"); myUrl.searchParams.set('rows', 10); myUrl.href 将包含更新后的URL - sprutex
2
根据@sprutex的评论,您可以将http://www.example.com?columns=5&rows=20替换为window.location.href以使代码更具动态性。 - Waleed Khaled
显示剩余5条评论
32个回答

1

我的解决方案:

const setParams = (data) => {
    if (typeof data !== 'undefined' && typeof data !== 'object') {
        return
    }

    let url = new URL(window.location.href)
    const params = new URLSearchParams(url.search)

    for (const key of Object.keys(data)) {
        if (data[key] == 0) {
            params.delete(key)
        } else {
            params.set(key, data[key])
        }
    }

    url.search = params
    url = url.toString()
    window.history.replaceState({ url: url }, null, url)
}

然后只需调用 "setParams" 并传递一个包含您要设置的数据的对象。
示例:
$('select').on('change', e => {
    const $this = $(e.currentTarget)
    setParams({ $this.attr('name'): $this.val() })
})

在我的情况下,当html select输入改变且值为"0"时,我需要更新它并删除参数。如果对象键是"null",您可以编辑函数并从url中删除参数。
希望这能帮到大家。

在你之前已经有两个使用URLSearchParams的相同答案了,好像你们谁都没有真正阅读答案。发布于2017年1月15日15:24回答,回答于2018年6月14日15:54。 - FantomX1

1

这是我的工作方式。使用我的editParams()函数,您可以添加、删除或更改任何参数,然后使用内置的replaceState()函数来更新URL:

window.history.replaceState('object or string', 'Title', 'page.html' + editParams('sorting', ModifiedTimeAsc));


// background functions below:

// add/change/remove URL parameter
// use a value of false to remove parameter
// returns a url-style string
function editParams (key, value) {
  key = encodeURI(key);

  var params = getSearchParameters();

  if (Object.keys(params).length === 0) {
    if (value !== false)
      return '?' + key + '=' + encodeURI(value);
    else
      return '';
  }

  if (value !== false)
    params[key] = encodeURI(value);
  else
    delete params[key];

  if (Object.keys(params).length === 0)
    return '';

  return '?' + $.map(params, function (value, key) {
    return key + '=' + value;
  }).join('&');
}

// Get object/associative array of URL parameters
function getSearchParameters () {
  var prmstr = window.location.search.substr(1);
  return prmstr !== null && prmstr !== "" ? transformToAssocArray(prmstr) : {};
}

// convert parameters from url-style string to associative array
function transformToAssocArray (prmstr) {
  var params = {},
      prmarr = prmstr.split("&");

  for (var i = 0; i < prmarr.length; i++) {
    var tmparr = prmarr[i].split("=");
    params[tmparr[0]] = tmparr[1];
  }
  return params;
}

没有评论的踩?代码有什么问题吗?它在许多情况下都运行得非常好。 - Bobb Fwed

1
如果您想更改地址栏中的URL:

const search = new URLSearchParams(location.search);
search.set('rows', 10);
location.search = search.toString();

注意,改变location.search会重新加载页面。

1

这里有一个简单的解决方案,使用 query-string 库。

const qs = require('query-string')
function addQuery(key, value) {
  const q = qs.parse(location.search)
  const url = qs.stringifyUrl(
    {
      url: location.pathname,
      query: {
      ...q,
      [key]: value,
      },
    },
    { skipEmptyString: true }
  );
  window.location.href = url
  // if you are using Turbolinks
  // add this: Turbolinks.visit(url)
}
// Usage
addQuery('page', 2)

如果你在使用 react 但没有使用 react-router
export function useAddQuery() {
  const location = window.location;
  const addQuery = useCallback(
    (key, value) => {
      const q = qs.parse(location.search);
      const url = qs.stringifyUrl(
        {
          url: location.pathname,
          query: {
            ...q,
            [key]: value,
          },
        },
        { skipEmptyString: true }
      );
      window.location.href = url
    },
    [location]
  );

  return { addQuery };
}
// Usage
const { addQuery } = useAddQuery()
addQuery('page', 2)

如果您正在使用 react-routerreact
export function useAddQuery() {
  const location = useLocation();
  const history = useHistory();

  const addQuery = useCallback(
    (key, value) => {
      let pathname = location.pathname;
      let searchParams = new URLSearchParams(location.search);
      searchParams.set(key, value);
      history.push({
        pathname: pathname,
        search: searchParams.toString()
      });
    },
    [location, history]
  );

  return { addQuery };
}

// Usage
const { addQuery } = useAddQuery()
addQuery('page', 2)

PS: qs 是从 query-string 模块导入的。


0

对 Sujoy 的答案进行了另一种变化。只是改变了变量名并添加了命名空间包装:

window.MyNamespace = window.MyNamespace  || {};
window.MyNamespace.Uri = window.MyNamespace.Uri || {};

(function (ns) {

    ns.SetQueryStringParameter = function(url, parameterName, parameterValue) {

        var otherQueryStringParameters = "";

        var urlParts = url.split("?");

        var baseUrl = urlParts[0];
        var queryString = urlParts[1];

        var itemSeparator = "";
        if (queryString) {

            var queryStringParts = queryString.split("&");

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

                if(queryStringParts[i].split('=')[0] != parameterName){

                    otherQueryStringParameters += itemSeparator + queryStringParts[i];
                    itemSeparator = "&";
                }
            }
        }

        var newQueryStringParameter = itemSeparator + parameterName + "=" + parameterValue;

        return baseUrl + "?" + otherQueryStringParameters + newQueryStringParameter;
    };

})(window.MyNamespace.Uri);

现在的用法是:

var changedUrl = MyNamespace.Uri.SetQueryStringParameter(originalUrl, "CarType", "Ford");

0

我也写过一个JavaScript中用于获取和设置URL查询参数的库

这是它使用的一个例子。

var url = Qurl.create()
  , query
  , foo
  ;

将查询参数作为对象获取,按键获取或添加/更改/删除。

// returns { foo: 'bar', baz: 'qux' } for ?foo=bar&baz=qux
query = url.query();

// get the current value of foo
foo = url.query('foo');

// set ?foo=bar&baz=qux
url.query('foo', 'bar');
url.query('baz', 'qux');

// unset foo, leaving ?baz=qux
url.query('foo', false); // unsets foo

0

0

1
现在应该是这个答案了!IE 是谁? - Mosh Feu

-1

我知道这是一个老问题。我已经增强了上面的函数,以添加或更新查询参数。仍然是纯JS解决方案。

                      function addOrUpdateQueryParam(param, newval, search) {

                        var questionIndex = search.indexOf('?');

                        if (questionIndex < 0) {
                            search = search + '?';
                            search = search + param + '=' + newval;
                            return search;
                        }

                        var regex = new RegExp("([?;&])" + param + "[^&;]*[;&]?");
                        var query = search.replace(regex, "$1").replace(/&$/, '');

                        var indexOfEquals = query.indexOf('=');

                        return (indexOfEquals >= 0 ? query + '&' : query + '') + (newval ? param + '=' + newval : '');
                    }

-1

我刚刚编写了一个简单的模块来处理读取和更新当前URL查询参数。

使用示例:

import UrlParams from './UrlParams'

UrlParams.remove('foo') //removes all occurences of foo=?
UrlParams.set('foo', 'bar') //set all occurences of foo equal to bar
UrlParams.add('foo', 'bar2') //add bar2 to foo result: foo=bar&foo=bar2
UrlParams.get('foo') //returns bar
UrlParams.get('foo', true) //returns [bar, bar2]

这是我的名为UrlParams.(js/ts)的代码:

class UrlParams {

    /**
     * Get params from current url
     * 
     * @returns URLSearchParams
     */
    static getParams(){
        let url = new URL(window.location.href)
        return new URLSearchParams(url.search.slice(1))
    }

    /**
     * Update current url with params
     * 
     * @param params URLSearchParams
     */
    static update(params){
        if(`${params}`){
            window.history.replaceState({}, '', `${location.pathname}?${params}`)
        } else {
            window.history.replaceState({}, '', `${location.pathname}`)
        }
    }

    /**
     * Remove key from url query
     * 
     * @param param string
     */
    static remove(param){
        let params = this.getParams()
        if(params.has(param)){
            params.delete(param)
            this.update(params)
        }
    }

    /**
     * Add key value pair to current url
     * 
     * @param key string
     * @param value string
     */
    static add(key, value){
        let params = this.getParams()
        params.append(key, value)
        this.update(params)
    }

    /**
     * Get value or values of key
     * 
     * @param param string
     * @param all string | string[]
     */
    static get(param, all=false){
        let params = this.getParams()
        if(all){
            return params.getAll(param)
        }
        return params.get(param)
    }

    /**
     * Set value of query param
     * 
     * @param key string
     * @param value string
     */
    static set(key, value){
        let params = this.getParams()
        params.set(key, value)
        this.update(params)
    }

}
export default UrlParams
export { UrlParams }

已经有4个与你提到的相同回复在帖子中发布,分别在2017年1月15日15:24回答,2018年6月14日15:54回答,2019年3月1日12:46回答以及2019年6月14日7:20回答。看起来好像没有人在发布之前阅读过这些回答。 - FantomX1

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