如何在 JavaScript 中删除查询字符串参数?

Posted

技术标签:

【中文标题】如何在 JavaScript 中删除查询字符串参数?【英文标题】:How can I delete a query string parameter in JavaScript? 【发布时间】:2010-12-10 17:20:23 【问题描述】:

除了使用正则表达式之外,有没有更好的方法从标准 javascript 中的 URL 字符串中的查询字符串中删除参数?

这是我迄今为止提出的,似乎在我的测试中有效,但我不喜欢重新发明查询字符串解析!

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;

【问题讨论】:

【参考方案1】:
"[&;]?" + parameter + "=[^&;]+"

看起来很危险,因为它的参数“bar”会匹配:

?a=b&foobar=c

另外,如果parameter 包含任何正则表达式中的特殊字符,例如“.”,它也会失败。而且它不是一个全局正则表达式,所以它只会删除参数的一个实例。

我不会为此使用简单的正则表达式,我会解析其中的参数并丢失您不想要的参数。

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;

【讨论】:

关于与 foobar 匹配的栏的要点。我已将原始正则表达式更新为需要 ?或以 [&;] 开头。还要阅读您的解决方案以考虑它... 如果你想摆脱“?”去掉后没有参数的时候,加一个if条件来测试pars.length==0,如果是0,则用“url = urlparts[0]”代替“?”。 将 URL 片段与 encodeURIComponent(parameter) 进行比较是否安全?如果 URL 以不同的方式对参数名称进行编码怎么办?例如“two%20words”与“two+words”。为了解决这个问题,最好将参数名称解​​码并将其作为普通字符串进行比较。 轻微改进,这样当最终的 URL 参数被移除时,'?'也被删除:将行 url= urlparts[0]+'?'+pars.join('&'); 更改为 url= urlparts[0] + (pars.length > 0 ? '?' + pars.join('&') : ""); @ktutnik/@JonasAxelsson URL 查询参数自然不区分大小写。【参考方案2】:

如果你喜欢 jQuery,有一个很好的查询字符串操作插件:

http://plugins.jquery.com/project/query-object

【讨论】:

第一个链接失效了;替代:github.com/fadhlirahim/jqURL. 谢谢,已删除 - 几年后它肯定会过时! :)【参考方案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;

【讨论】:

【参考方案4】:

复制自 bobince 答案,但使其支持查询字符串中的问号,例如

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

Is it valid to have more than one question mark in a 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;

【讨论】:

我认为??? 是无效语法,不应出现在 URL 中。 @torazaburo 看看我发布的 *** 问题:“URL 中包含多个问号是否有效?”,答案似乎是肯定的。这也是几年前的事了,所以我不记得细节了,但是当没有正确处理时我遇到了问题。 我并不是说它们在现实世界中不存在,人们可能希望能够处理它们,但是在格式正确的 URL 中,问号是“保留字符”并且除了引入查询参数的问号之外的任何问号都应该是 URL 编码的。 您可能希望将最后一行替换为return url.endsWith("?") ? url.slice(0,-1) : url;,以涵盖要删除的参数是查询字符串中唯一的参数的情况 @Konamiman 例如,当从 google.com/search?q=test???&aq=f 中删除“aq”时,这会改变参数数据,但我明白你的意思,即使 ?不会造成任何伤害。逻辑只需要确保最后一个?也是第一个?。【参考方案5】:

任何对正则表达式解决方案感兴趣的人我都将这个函数放在一起来添加/删除/更新查询字符串参数。不提供值将删除参数,提供值将添加/更新参数。如果没有提供 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 更新以修复在直接删除主题标签之前的查询字符串变量时主题标签符号丢失的情况

【讨论】:

如果您有两个查询字符串并删除第一个,这将不起作用。传入的 url 变得无效,因为 ?在应该保留时被删除。 @BlakeNiemyjski 感谢您发现该错误,我已更新脚本以包含第一个参数的解决方法 会不小心删除这里的哈希:UpdateQueryString('a', null, 'http://www.test.com?a=b#c'); 很酷的功能,谢谢。仅供参考:在 each()` 循环中将其与忽略数组键一起使用时,您可能需要为每次替换迭代定义一个不断缩小的 url。但是,这意味着您必须在参数中输入 value,这将使查询字符串被删除一半。为了解决这个问题,请使用undefinednull 作为value 参数,例如:url_from_last_iteration = UpdateQueryString(current_ignore_key, undefined/null, url_from_last_iteration);【参考方案6】:

此线程上的所有响应都有一个缺陷,即它们不保留 URL 的锚/片段部分。

所以如果你的 URL 看起来像:

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

然后你替换“参数”

你会丢失你的片段文本。

以下是解决此问题的先前答案(通过 LukePH 的 bobince)的改编:

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;

【讨论】:

轻微改进,这样当最终的 URL 参数被移除时,'?'也被删除:将行 url = urlBase+'?'+pars.join('&'); 更改为 url = urlBase + (pars.length > 0 ? '?' + pars.join('&') : ""); 如果 # 先出现怎么办? dns-entry/path#fragment-text?parameter=value【参考方案7】:

我没有看到正则表达式解决方案存在重大问题。但是,不要忘记保留片段标识符(# 之后的文本)。

这是我的解决方案:

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

对于 bobince 来说,是的 - 您需要在参数名称中转义 . 字符。

【讨论】:

这是一个改进的正则表达式,当参数没有值(即'ex.com?removeMe')时有效,并且不会替换片段中的参数(即'ex.com?#&dont= removeMe')或路径(即'ex.com/&dont=removeMe'):url.replace(new RegExp('^([^#]*\?)(([^#]*)&)?' + parameter + '(\=[^&#]*)?(&|#|$)' ), '$1$3$5').replace(/^([^#]*)((\?)&|\?(#|$))/,'$1$3$4') 这行不通 Stephen M. Harris。尝试给你的代码一个空字符串作为参数,看看会发生什么......【参考方案8】:

您应该使用库来进行 URI 操作,因为它比表面上看起来要自己操作要复杂得多。看一看:http://medialize.github.io/URI.js/

【讨论】:

【参考方案9】:
function removeQueryStringParameter(uri, key, value) 


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

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

    if (uri.match(re)) 

        return uri.replace(re, '');

    

【讨论】:

【参考方案10】:

假设你想从 URI 中移除 key=val 参数:

function removeParam(uri) 
   return uri.replace(/([&\?]key=val*$|key=val&|[?&]key=val(?=#))/, '');

【讨论】:

效果很好,但在正则表达式中转义第一个问号是不必要的,并且可能导致 linter 错误:/([&?]key=val*$|key=val&|[?&]key=val(?=#))/ 在使用像 eslint 这样的 linter 时可能更可取【参考方案11】:

由 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

【讨论】:

发送参数值时要记住的一件事将空间转换为 %20【参考方案12】:

这将返回不带任何 GET 参数的 URL:

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 );

【讨论】:

【参考方案13】:

这是一个完整的函数,用于根据这个问题和这个 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% 确定这个东西是否有一些缺陷,但据我测试它工作得很好。

【讨论】:

【参考方案14】:

据我所知,以上都不能处理普通参数和数组参数。这是一个。

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

当然,要更新参数,只需删除然后添加即可。随意为它制作一个虚拟函数。

【讨论】:

【参考方案15】:

使用 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;

【讨论】:

【参考方案16】:

Modern browsers 提供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`)

【讨论】:

请注意,IE、Edge 16 和 ios 10.2 Safari 不支持 URLSearchParams。 (参考:caniuse.com/#feat=urlsearchparams) @khiavreoy 是的。就像答案中的前两个词给出相同的链接:)【参考方案17】:

这是我正在使用的:

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

原始网址:http://www.example.com/test/hello?id=123&foo=bar 目标网址:http://www.example.com/test/hello

【讨论】:

您是否在页面加载时编写此代码?我问你是因为当我写这个页面加载与否时,它都不起作用。【参考方案18】:

您可以通过以下方式更改 URL:

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

这样,你可以在没有搜索参数的情况下覆盖URL,我在获取GET参数后使用它来清理URL。

【讨论】:

如果只有一个搜索参数需要删除而不更改其他搜索参数怎么办?谢谢! 正是我所需要的。谢谢。【参考方案19】:

这是一个干净的版本删除查询参数,带有 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 以下)不支持 URL 类中的 URLSearchParams。

Polyfills

仅 URLSearchParams 填充

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

完整的 Polyfill URL 和 URLSearchParams 以匹配最新的 WHATWG 规范

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

【讨论】:

【参考方案20】:

这里有一个解决方案:

    使用URLSearchParams(正则表达式不难理解) 更新搜索栏中的网址,无需重新加载 维护 URL 的所有其他部分(例如哈希) 如果删除了最后一个参数,则删除查询字符串中多余的?
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 是not supported in IE,因此请使用polyfill。

【讨论】:

【参考方案21】:
const params = new URLSearchParams(location.search)
params.delete('key_to_delete')
console.log(params.toString())

【讨论】:

这是一个非常古老的问题的答案,并且已经有一个公认的答案。请解释这个答案必须提供什么是新的/不同于其他答案的。此外,答案应包括解释,而不仅仅是代码。【参考方案22】:

我实际上编写了以下函数来处理 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']);

);

我觉得很有用!

【讨论】:

【参考方案23】:

另一个直接且更简单的答案是

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

【讨论】:

【参考方案24】:

很高兴您滚动到这里。

我建议您通过下一个可能的解决方案来解决此任务:

    您只需要支持现代浏览器 (Edge >= 17) - 使用 URLSearchParams.delete() API。它是原生的,显然是解决此任务的最便捷方式。 如果这不是一个选项,您可能需要编写一个函数来执行此操作。 Such a function 确实 如果参数不存在,请不要更改 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``;  

See how it works here

【讨论】:

【参考方案25】:
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;

【讨论】:

【参考方案26】:

如果是URL的实例,使用searchParamsdelete函数

let url = new URL(location.href);
url.searchParams.delete('page');

【讨论】:

请注意,IE11 不支持“URL”:caniuse.com/?search=URL【参考方案27】:

如果您有 URLSearchParams 的 polyfill,或者根本不需要支持 Internet Explorer,那么我会使用这里的其他答案中建议的内容。如果你不想依赖URLSearchParams,我会这样做:

function removeParameterFromUrl(url, parameter) 
  const replacer = (m, p1, p2) => (p1 === '?' && p2 === '&' ? '?' : p2 || '')
  return url.replace(new RegExp(`([?&])$parameter=[^&#]+([&#])?`), replacer)

它将以?替换前面为?p1)和后面&p2)的参数,以确保参数列表仍然以问号开头,否则,它将用下一个分隔符 (p2) 替换它:可以是&,或#,或undefined,它回退为一个空字符串。

【讨论】:

以上是关于如何在 JavaScript 中删除查询字符串参数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在javascript中访问请求查询字符串参数?

如何在 Javascript 中创建查询参数?

从查询字符串中删除一个参数的正则表达式

如何在 javascript 中解析特定查询参数的 URL?

在javascript中搜索和替换特定的查询字符串参数值

如何使用 Javascript 构建查询字符串