Как удалить параметр строки запроса в JavaScript?

128

Есть ли лучший способ удалить параметр из строки запроса в строке URL в стандартном JavaScript, кроме использования регулярного выражения?

Вот то, что я придумал до сих пор, что, кажется, работает в моих тестах, но я не люблю изобретать заново разбор строки запроса!

function RemoveParameterFromUrl( url, parameter ) {

    if( typeof parameter == "undefined" || parameter == null || parameter == "" ) throw new Error( "parameter is required" );

    url = url.replace( new RegExp( "\\b" + parameter + "=[^&;]+[&;]?", "gi" ), "" ); "$1" );

    // remove any leftover crud
    url = url.replace( /[&;]$/, "" );

    return url;
}
Мэтью Лок
источник

Ответы:

178
"[&;]?" + parameter + "=[^&;]+"

Кажется опасным, потому что ему соответствует параметр bar:

?a=b&foobar=c

Кроме того, он не сработает, если он parameterсодержит какие-либо символы, которые являются специальными в RegExp, например '.'. И это не глобальное регулярное выражение, поэтому он удалит только один экземпляр параметра.

Я бы не стал использовать для этого простой RegExp, я бы проанализировал параметры и потерял те, которые вам не нужны.

function removeURLParameter(url, parameter) {
    //prefer to use l.search if you have a location/link object
    var urlparts = url.split('?');   
    if (urlparts.length >= 2) {

        var prefix = encodeURIComponent(parameter) + '=';
        var pars = urlparts[1].split(/[&;]/g);

        //reverse iteration as may be destructive
        for (var i = pars.length; i-- > 0;) {    
            //idiom for string.startsWith
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {  
                pars.splice(i, 1);
            }
        }

        return urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : '');
    }
    return url;
}
bobince
источник
Хорошее замечание о баре, соответствующем foobar. Я обновил исходное регулярное выражение, чтобы требовать? или [&;] в начале. Также прочтите ваше решение, чтобы рассмотреть его ...
Мэтью Лок
5
Если вы хотите избавиться от символа "?" если после удаления параметров нет, добавьте условие if для проверки, если pars.length == 0, и если оно равно 0, то сделайте «url = urlparts [0]» вместо добавления «?».
johnmcaliley
2
Безопасно ли сравнивать фрагмент URL-адреса с encodeURIComponent (параметр)? Что, если URL-адрес кодирует имя параметра по-другому? Например, «два% 20 слов» вместо «два + слова». Чтобы справиться с этим, может быть лучше декодировать имя параметра и сравнить его как обычную строку.
Адриан Пронк
9
Небольшое улучшение, так что при удалении параметра конечного URL знак '?' тоже удаляется: Измените строку url= urlparts[0]+'?'+pars.join('&');наurl= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : "");
Cody S
2
@ ktutnik / @ JonasAxelsson Параметры URL-запроса не чувствительны к регистру.
bobince
30

Современные браузеры предоставляют URLSearchParamsинтерфейс для работы с параметрами поиска. У которого есть deleteметод, который удаляет параметр по имени.

if (typeof URLSearchParams !== 'undefined') {
  const params = new URLSearchParams('param1=1&param2=2&param3=3')
  
  console.log(params.toString())
  
  params.delete('param2')
  
  console.log(params.toString())

} else {
  console.log(`Your browser ${navigator.appVersion} does not support URLSearchParams`)
}

Юрий Тарабанко
источник
2
Обратите внимание, что URLSearchParamsне поддерживается IE, Edge 16 и iOS 10.2 Safari. (ref: caniuse.com/#feat=urlsearchparams )
khiav reoy
3
@khiavreoy Ага. Как и первые два слова в ответе, дайте ту же ссылку :)
Юрий Тарабанко
23

Скопировано из ответа bobince, но он поддерживает вопросительные знаки в строке запроса, например

http://www.google.com/search?q=test???+something&aq=f

Допустимо ли иметь в URL более одного вопросительного знака?

function removeUrlParameter(url, parameter) {
  var urlParts = url.split('?');

  if (urlParts.length >= 2) {
    // Get first part, and remove from array
    var urlBase = urlParts.shift();

    // Join it back up
    var queryString = urlParts.join('?');

    var prefix = encodeURIComponent(parameter) + '=';
    var parts = queryString.split(/[&;]/g);

    // Reverse iteration as may be destructive
    for (var i = parts.length; i-- > 0; ) {
      // Idiom for string.startsWith
      if (parts[i].lastIndexOf(prefix, 0) !== -1) {
        parts.splice(i, 1);
      }
    }

    url = urlBase + '?' + parts.join('&');
  }

  return url;
}
LukePH
источник
2
Я считаю, что ???это недопустимый синтаксис и никогда не должен встречаться в URL`.
@torazaburo Взгляните на вопрос stackoverflow, который я опубликовал: «Допустимо ли иметь более одного вопросительного знака в URL-адресе?», ответ будет положительным. Также это было много лет назад, поэтому я не могу вспомнить детали, но я столкнулся с проблемами, когда это было неправильно обработано.
LukePH,
Я не говорю, что они не существуют в реальном мире, и кто-то, вероятно, захотел бы иметь возможность обрабатывать их, но в правильно сформированном URL-адресе вопросительный знак является «зарезервированным символом», а любой вопросительный знак, кроме этого вводимые параметры запроса должны быть закодированы в URL.
1
Вы можете заменить последнюю строку на, return url.endsWith("?") ? url.slice(0,-1) : url;чтобы охватить случай, когда параметр, который нужно удалить, является единственным в строке запроса
Konamiman
@Konamiman Это изменит данные параметров, например, при удалении 'aq' из: google.com/search?q=test???&aq=f, но я понимаю, что вы имеете в виду, было бы неплохо очистить URL-адрес, даже если ? не причиняет никакого вреда. В логике просто нужно убедиться, последнее? тоже первый ?.
LukePH
22

Я не вижу серьезных проблем с решением регулярных выражений. Но не забудьте сохранить идентификатор фрагмента (текст после #).

Вот мое решение:

function RemoveParameterFromUrl(url, parameter) {
  return url
    .replace(new RegExp('[?&]' + parameter + '=[^&#]*(#.*)?$'), '$1')
    .replace(new RegExp('([?&])' + parameter + '=[^&]*&'), '$1');
}

И что касается bobince, да - вам нужно будет экранировать .символы в именах параметров.

Джаред
источник
1
Вот улучшенное регулярное выражение, которое работает, когда параметр не имеет значения (например, «ex.com?removeMe»), и не заменяет параметр во фрагментах (например, «ex.com?#&dont=removeMe») или путях (например, « ex.com/&dont=removeMe '):url.replace(new RegExp('^([^#]*\?)(([^#]*)&)?' + parameter + '(\=[^&#]*)?(&|#|$)' ), '$1$3$5').replace(/^([^#]*)((\?)&|\?(#|$))/,'$1$3$4')
Стивен М. Харрис
Это не сработает, Стивен М. Харрис. Попробуйте указать в своем коде пустую строку в качестве параметра и посмотрите, что произойдет ...
Дэвид Фишер,
15

Вы можете изменить URL-адрес с помощью:

window.history.pushState({}, document.title, window.location.pathname);

таким образом вы можете перезаписать URL без параметра поиска, я использую его для очистки URL после получения параметров GET.

Санти Нуньес
источник
13

Всем, кто интересуется решением с регулярными выражениями, я собрал эту функцию для добавления / удаления / обновления параметра строки запроса. Если не указать значение, параметр будет удален, а при вводе - добавлен / обновлен параметр. Если URL не указан, он будет взят из window.location. Это решение также учитывает привязку URL-адреса.

function UpdateQueryString(key, value, url) {
    if (!url) url = window.location.href;
    var re = new RegExp("([?&])" + key + "=.*?(&|#|$)(.*)", "gi"),
        hash;

    if (re.test(url)) {
        if (typeof value !== 'undefined' && value !== null)
            return url.replace(re, '$1' + key + "=" + value + '$2$3');
        else {
            hash = url.split('#');
            url = hash[0].replace(re, '$1$3').replace(/(&|\?)$/, '');
            if (typeof hash[1] !== 'undefined' && hash[1] !== null) 
                url += '#' + hash[1];
            return url;
        }
    }
    else {
        if (typeof value !== 'undefined' && value !== null) {
            var separator = url.indexOf('?') !== -1 ? '&' : '?';
            hash = url.split('#');
            url = hash[0] + separator + key + '=' + value;
            if (typeof hash[1] !== 'undefined' && hash[1] !== null) 
                url += '#' + hash[1];
            return url;
        }
        else
            return url;
    }
}

ОБНОВИТЬ

Произошла ошибка при удалении первого параметра в строке запроса, я переработал регулярное выражение и тест, чтобы включить исправление.

ОБНОВЛЕНИЕ 2

Обновление @schellmax для исправления ситуации, когда символ хэштега теряется при удалении переменной строки запроса непосредственно перед хэштегом

ellemayo
источник
1
Это не сработает, если у вас есть две строки запроса и вы удалите первую. Переданный URL-адрес становится недействительным, потому что? удаляется, когда он должен быть сохранен.
Blake Niemyjski 06
1
@BlakeNiemyjski, спасибо за обнаружение этой ошибки, я обновил скрипт, чтобы включить обходной путь для первого параметра
ellemayo 07
1
случайно удалит хеш здесь:UpdateQueryString('a', null, 'http://www.test.com?a=b#c');
schellmax
Классная функция, спасибо. К вашему сведению: при использовании этого с игнорируемыми ключами массива в циклах each () `вам может потребоваться определить постоянное сжатие urlдля каждой итерации замены. Но это означает, что вы должны ввести valueв аргументы, что оставит строку запроса наполовину удаленной. Чтобы противостоять этому, используйте undefinedили nullв качестве valueаргумента, например:url_from_last_iteration = UpdateQueryString(current_ignore_key, undefined/null, url_from_last_iteration);
dhaupin
7

Предполагая, что вы хотите удалить параметр key = val из URI:

function removeParam(uri) {
   return uri.replace(/([&\?]key=val*$|key=val&|[?&]key=val(?=#))/, '');
}
ssh_imov
источник
Работает хорошо, но экранирование первого вопросительного знака в регулярном выражении необязательно и может вызвать ошибку линтера: /([&?]key=val*$|key=val&|[?&]key=val(?=#))/может быть предпочтительнее при использовании линтера,
такого
7

Вот что я использую:

if (location.href.includes('?')) { 
    history.pushState({}, null, location.href.split('?')[0]); 
}

Исходный URL: http://www.example.com/test/hello?id=123&foo=bar
Целевой URL: http://www.example.com/test/hello

Basj
источник
Вы пишете этот код при загрузке страницы? Я спрашиваю вас, потому что, когда я пишу это, страница загружается или нет, это не работает.
noobprogrammer
6

Вот полная функция для добавления и удаления параметров на основе этого вопроса и этого github gist: https://gist.github.com/excalq/2961415

var updateQueryStringParam = function (key, value) {

    var baseUrl = [location.protocol, '//', location.host, location.pathname].join(''),
        urlQueryString = document.location.search,
        newParam = key + '=' + value,
        params = '?' + newParam;

    // If the "search" string exists, then build params from it
    if (urlQueryString) {

        updateRegex = new RegExp('([\?&])' + key + '[^&]*');
        removeRegex = new RegExp('([\?&])' + key + '=[^&;]+[&;]?');

        if( typeof value == 'undefined' || value == null || value == '' ) { // Remove param if value is empty

            params = urlQueryString.replace(removeRegex, "$1");
            params = params.replace( /[&;]$/, "" );

        } else if (urlQueryString.match(updateRegex) !== null) { // If param exists already, update it

            params = urlQueryString.replace(updateRegex, "$1" + newParam);

        } else { // Otherwise, add it to end of query string

            params = urlQueryString + '&' + newParam;

        }

    }
    window.history.replaceState({}, "", baseUrl + params);
};

Вы можете добавить такие параметры:

updateQueryStringParam( 'myparam', 'true' );

И снимаем вот так:

updateQueryStringParam( 'myparam', null );

В этом потоке многие говорили, что регулярное выражение, вероятно, не лучшее / стабильное решение ... так что я не уверен на 100%, есть ли у этой вещи какие-то недостатки, но насколько я ее тестировал, она работает довольно хорошо.

гды
источник
5

Это чистая версия параметра запроса удаления с классом URL для современных браузеров:

function removeUrlParameter(url, paramKey)
{
  var r = new URL(url);
  r.searchParams.delete(paramKey);
  return r.href;
}

URLSearchParams не поддерживается в старых браузерах

https://caniuse.com/#feat=urlsearchparams

IE, Edge (ниже 17) и Safari (ниже 10.3) не поддерживают URLSearchParams внутри класса URL.

Polyfills

Только URLSearchParams полифил

https://github.com/WebReflection/url-search-params

Полный URL-адрес Polyfill и URLSearchParams для соответствия последним спецификациям WHATWG

https://github.com/lifaon74/url-polyfill

Героселохим
источник
4

Используя jQuery:

function removeParam(key) {
    var url = document.location.href;
    var params = url.split('?');
    if (params.length == 1) return;

    url = params[0] + '?';
    params = params[1];
    params = params.split('&');

    $.each(params, function (index, value) {
        var v = value.split('=');
        if (v[0] != key) url += value + '&';
    });

    url = url.replace(/&$/, '');
    url = url.replace(/\?$/, '');

    document.location.href = url;
}
Huy Phạm
источник
3

Вышеупомянутая версия как функция

function removeURLParam(url, param)
{
 var urlparts= url.split('?');
 if (urlparts.length>=2)
 {
  var prefix= encodeURIComponent(param)+'=';
  var pars= urlparts[1].split(/[&;]/g);
  for (var i=pars.length; i-- > 0;)
   if (pars[i].indexOf(prefix, 0)==0)
    pars.splice(i, 1);
  if (pars.length > 0)
   return urlparts[0]+'?'+pars.join('&');
  else
   return urlparts[0];
 }
 else
  return url;
}
Грэхем
источник
2

Вам следует использовать библиотеку для манипуляций с URI, поскольку сделать это самостоятельно сложнее, чем кажется на первый взгляд. Взгляните на: http://medialize.github.io/URI.js/

Райан
источник
2

Насколько я могу судить, ни одно из вышеперечисленных не может обрабатывать обычные параметры и параметры массива. Вот такой.

function removeURLParameter(param, url) {
    url = decodeURI(url).split("?");
    path = url.length == 1 ? "" : url[1];
    path = path.replace(new RegExp("&?"+param+"\\[\\d*\\]=[\\w]+", "g"), "");
    path = path.replace(new RegExp("&?"+param+"=[\\w]+", "g"), "");
    path = path.replace(/^&/, "");
    return url[0] + (path.length
        ? "?" + path
        : "");
}

function addURLParameter(param, val, url) {
    if(typeof val === "object") {
        // recursively add in array structure
        if(val.length) {
            return addURLParameter(
                param + "[]",
                val.splice(-1, 1)[0],
                addURLParameter(param, val, url)
            )
        } else {
            return url;
        }
    } else {
        url = decodeURI(url).split("?");
        path = url.length == 1 ? "" : url[1];
        path += path.length
            ? "&"
            : "";
        path += decodeURI(param + "=" + val);
        return url[0] + "?" + path;
    }
}

Как это использовать:

url = location.href;
    -> http://example.com/?tags[]=single&tags[]=promo&sold=1

url = removeURLParameter("sold", url)
    -> http://example.com/?tags[]=single&tags[]=promo

url = removeURLParameter("tags", url)
    -> http://example.com/

url = addURLParameter("tags", ["single", "promo"], url)
    -> http://example.com/?tags[]=single&tags[]=promo

url = addURLParameter("sold", 1, url)
    -> http://example.com/?tags[]=single&tags[]=promo&sold=1

Конечно, чтобы обновить параметр, просто удалите, а затем добавьте. Не стесняйтесь сделать для него фиктивную функцию.

Кейр Симмонс
источник
path.replace(new RegExp("&?"+param+"=[\\w]+", "g"), "");Я бы изменил регулярное выражение, чтобы [\\w]*включить такие параметры, как "param =" без значений.
Томас Прадо
2

Все ответы в этой цепочке имеют недостаток в том, что они не сохраняют якорные / фрагментарные части URL-адресов.

Итак, если ваш URL-адрес выглядит так:

http://dns-entry/path?parameter=value#fragment-text

и вы заменяете 'параметр'

вы потеряете фрагмент текста.

Ниже приводится адаптация предыдущих ответов (bobince через LukePH), которая решает эту проблему:

function removeParameter(url, parameter)
{
  var fragment = url.split('#');
  var urlparts= fragment[0].split('?');

  if (urlparts.length>=2)
  {
    var urlBase=urlparts.shift(); //get first part, and remove from array
    var queryString=urlparts.join("?"); //join it back up

    var prefix = encodeURIComponent(parameter)+'=';
    var pars = queryString.split(/[&;]/g);
    for (var i= pars.length; i-->0;) {               //reverse iteration as may be destructive
      if (pars[i].lastIndexOf(prefix, 0)!==-1) {   //idiom for string.startsWith
        pars.splice(i, 1);
      }
    }
    url = urlBase + (pars.length > 0 ? '?' + pars.join('&') : '');
    if (fragment[1]) {
      url += "#" + fragment[1];
    }
  }
  return url;
}
Брет Вайнрауб
источник
1
Небольшое улучшение, так что при удалении параметра конечного URL знак '?' тоже удаляется: Измените строку url = urlBase+'?'+pars.join('&');наurl = urlBase + (pars.length > 0 ? '?' + pars.join('&') : "");
Cody S
что если # будет первым? dns-entry / path # fragment-text? parameter = value
ajayv
2

Вот решение, которое:

  1. использует URLSearchParams (нетрудно понять регулярное выражение)
  2. обновляет URL-адрес в строке поиска без перезагрузки
  3. поддерживает все остальные части URL (например, хэш)
  4. удаляет лишнее? в строке запроса, если был удален последний параметр
function removeParam(paramName) {
    let searchParams = new URLSearchParams(window.location.search);
    searchParams.delete(paramName);
    if (history.replaceState) {
        let searchString = searchParams.toString().length > 0 ? '?' + searchParams.toString() : '';
        let newUrl = window.location.protocol + "//" + window.location.host + window.location.pathname +  searchString + window.location.hash;
        history.replaceState(null, '', newUrl);
    }
}

Примечание: как указано в других ответах, URLSearchParams не поддерживается в IE , поэтому используйте полифилл .

klues
источник
2

Если это экземпляр URL, используйте deleteфункциюsearchParams

let url = new URL(location.href);
url.searchParams.delete('page');
Wariored
источник
1

другой прямой и более простой ответ был бы

let url = new URLSearchParams(location.search)
let key = 'some_key'

return url.has(key)
    ? location.href.replace(new RegExp(`[?&]${key}=${url.get(key)}`), '')
    : location.href
ctf0
источник
0

Модифицированная версия решения от ssh_imov

function removeParam(uri, keyValue) {
      var re = new RegExp("([&\?]"+ keyValue + "*$|" + keyValue + "&|[?&]" + keyValue + "(?=#))", "i"); 
      return uri.replace(re, '');
    }

Звоните так

removeParam("http://google.com?q=123&q1=234&q2=567", "q1=234");
// returns http://google.com?q=123&q2=567
kiranvj
источник
одна вещь, которую следует иметь в виду при отправке значения параметра преобразования пространства в% 20
xeon zolt
0

Это возвращает URL-адрес без ЛЮБЫХ параметров GET:

var href = document.location.href;
var search = document.location.search;
var pos = href.indexOf( search );
if ( pos !== -1 ){
    href = href.slice( 0, pos );
    console.log( href );
}
Дэвид Фреймаучер
источник
0

Я практически написал следующую функцию для обработки параметров url и получения окончательного статуса в виде строки и перенаправления страницы. Надеюсь, это принесет пользу.

function addRemoveUrlQuery(addParam = {}, removeParam = [], startQueryChar = '?'){

    let urlParams = new URLSearchParams(window.location.search);

    //Add param
    for(let i in addParam){
        if(urlParams.has(i)){ urlParams.set(i, addParam[i]); }
        else                { urlParams.append(i, addParam[i]); }
    }

    //Remove param
    for(let i of removeParam){
        if(urlParams.has(i)){
            urlParams.delete(i);
        }
    }

    if(urlParams.toString()){
        return startQueryChar + urlParams.toString();
    }

    return '';
}

Например, когда я нажимаю кнопку, я хочу, чтобы значение страницы было удалено, а значение категории было добавлено.

let button = document.getElementById('changeCategory');
button.addEventListener('click', function (e) {

    window.location = addRemoveUrlQuery({'category':'cars'}, ['page']);

});

Думаю, это было очень полезно!

Эмра Тунджел
источник
0

Рад, что вы прокрутили здесь.

Предлагаю вам решить эту задачу следующими возможными решениями:

  1. Вам необходимо поддерживать только современные браузеры (Edge> = 17) - используйте API URLSearchParams.delete () . Он родной и, очевидно, самый удобный способ решения этой задачи.
  2. Если это не вариант, вы можете написать функцию для этого. Такая функция делает
    • не менять URL, если параметр не указан
    • удалить параметр URL без значения, например http://google.com/?myparm
    • удалить параметр URL со значением, например http://google.com/?myparm=1
    • удалить параметр URL, если он присутствует в URL дважды, например http://google.com?qp=1&qpqp=2&qp=1
    • Не использует forцикл и не изменяет массив во время цикла по нему
    • более функциональный
    • более читабелен, чем решения с регулярным выражением
    • Перед использованием убедитесь, что ваш URL не закодирован

Работает в IE> 9 (версия ES5)

function removeParamFromUrl(url, param) {  // url: string, param: string
  var urlParts = url.split('?'),
      preservedQueryParams = '';

  if (urlParts.length === 2) {
    preservedQueryParams = urlParts[1]
      .split('&')
      .filter(function(queryParam) {
        return !(queryParam === param || queryParam.indexOf(param + '=') === 0)
      })
      .join('&');
  }

  return urlParts[0] +  (preservedQueryParams && '?' + preservedQueryParams); 
}

Необычная версия ES6

function removeParamFromUrlEs6(url, param) {
  const [path, queryParams] = url.split('?');
	let preservedQueryParams = '';

  if (queryParams) {
    preservedQueryParams = queryParams
      .split('&')
      .filter(queryParam => !(queryParam === param || queryParam.startsWith(`${param}=`)))
      .join('&');
  }

  return `${path}${preservedQueryParams && `?${preservedQueryParams}`}`;  
}

Посмотрите, как это работает здесь

Шевченко Виктор
источник
0
function removeParamInAddressBar(parameter) {
    var url = document.location.href;
    var urlparts = url.split('?');

    if (urlparts.length >= 2) {
        var urlBase = urlparts.shift();
        var queryString = urlparts.join("?");

        var prefix = encodeURIComponent(parameter) + '=';
        var pars = queryString.split(/[&;]/g);
        for (var i = pars.length; i-- > 0;) {
            if (pars[i].lastIndexOf(prefix, 0) !== -1) {
                pars.splice(i, 1);
            }
        }

        if (pars.length == 0) {
            url = urlBase;
        } else {
            url = urlBase + '?' + pars.join('&');
        }

        window.history.pushState('', document.title, url); // push the new url in address bar
    }
    return url;
}
Alex
источник
-1
const params = new URLSearchParams(location.search)
params.delete('key_to_delete')
console.log(params.toString())
Нирадж Патхак
источник
Это ответ на очень старый вопрос, на который уже есть принятый ответ. Пожалуйста, объясните, что предлагает этот ответ, что нового / отличается от других ответов. Кроме того, ответы должны включать пояснения, а не только код.
nurdyguy
-2

Если вам нравится jQuery, есть хороший плагин для работы со строкой запроса:

Damovisa
источник
1
Первая из этих ссылок мертва; альтернатива: github.com/fadhlirahim/jqURL .
Мартин Карпентер,
Спасибо, удалил - через пару лет он обязательно устареет! :)
Дамовиса
-2
function removeQueryStringParameter(uri, key, value) 
{

var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i");

    var separator = uri.indexOf('?') !== -1 ? "&" : "?";

    if (uri.match(re)) {

        return uri.replace(re, '');

    }
}
Прасад Патил
источник