Обновить параметры в URL с помощью history.pushState()

Я использую history.pushState, чтобы добавить несколько параметров к текущему URL-адресу страницы после вызова AJAX на моей странице. Теперь на той же странице, основанной на действии пользователя, я хочу снова обновить URL страницы с помощью того же или дополнительного набора параметров. Поэтому мой код выглядит так:

var pageUrl = window.location.href + "?" + queryString;
window.history.pushState('','',pageUrl);

queryString - это мой список параметров запроса.

Но с приведенным выше кодом мои параметры добавляются к URL с параметрами, и они выглядят ниже после второго вызова AJAX:

http://sample.com?param1=foo&param2=bar&param1=foo,foo1&param2=bar&param3=another_foo

Итак, параметры появляются дважды в URL-адресе, есть ли способ заменить параметры в URL-адресе, прежде чем нажимать на "История" или любой другой лучший способ достичь этого в javascript (jquery)?

Ответ 1

Я думаю, что вам нужно, это удалить window.location.href и оставить '?' + '?' +

var pageUrl = '?' + queryString;
window.history.pushState('', '', pageUrl);

Ответ 2

Эта функция может быть полезна

function updateUrlParameter(param, value) {
    const regExp = new RegExp(param + "(.+?)(&|$)", "g");
    const newUrl = window.location.href.replace(regExp, param + "=" + value + "$2");
    window.history.pushState("", "", newUrl);
}

Изменить: следующее решение проще, и оно также работает, если параметр еще не является частью URL. Тем не менее, он не поддерживается Internet Explorer (вы не говорите?).

function setQueryStringParameter(name, value) {
    const params = new URLSearchParams(location.search);
    params.set(name, value);
    window.history.replaceState({}, "", decodeURIComponent('${location.pathname}?${params}'));
}

Ответ 3

Вот функция, которую я использую для этого. (Большая часть кредита идет здесь).

Использование:

setQueryStringParameter("param1","foo"); //pushes a new history state of ?param1=foo
setQueryStringParameter({param1:"foo",param2:"bar"}); //pushes multiple changes
setQueryStringParameter({param3:"another foo"},{type:"replace"}); //replace history instead of push

Код:

function setQueryStringParameter(key, value, options) {

    var baseUrl         = [location.protocol, '//', location.host, location.pathname].join(''),
        q               = document.location.search,
        changes         = {},
        aType           = typeof(key),
        clear           = false;

    if(aType == "string"){
        changes[key] = value;
    }else if(aType == "object"){
        changes = key;
        options = value;
    }else if(key === false){
        clear = true;
    }

    //Options
    if(!options) options = {};
    var historyType     = options.type ? options.type : "push",
        state           = options.state ? options.state : {},
        title           = options.title ? options.title : "";


    if(clear){
        q = "";
    }else{
        var escapeRegExp = function(string){ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')};
        for (var key in changes) {
            var value       = changes[key];
            var newParam    = key + '=' + encodeURIComponent(value);
            var updateRegex = new RegExp('([\?&])' + escapeRegExp(key) + '[^&]*');
            var removeRegex = new RegExp('([\?&])' + escapeRegExp(key) + '=[^&;]+[&;]?');

            if( typeof value == 'undefined' || value == null || value == '' ) { // Remove param if value is empty
                q = q.replace(removeRegex, "$1");
                q = q.replace( /[&;]$/, "" );
            } else if (q.match(updateRegex) !== null) { // If param exists already, update it
                q = q.replace(updateRegex, "$1" + newParam);
            } else { // Otherwise, add it to end of query string
                var join = q ? "&" : "?";
                q = q + join + newParam;
            }

        }
    }


    if(q == "?") q = "";
    window.history[historyType+"State"](state, title, baseUrl + q);

    return !!q; //Return true if there a query string, false otherwise
}