JS 删除指定的查询参数

Last Modified: 2023/05/06

概述

本文讲述如何解析查询参数,并分享两种删除 url 中指定查询参数的方法。

解析查询参数

查询参数(query param)是 URL 中的一部分,通常使用查询参数给指定的 url 传递数据。查询参数出现在 URL 的 ? 后面并使用 符号分隔。举个例子:

https://verytools.net/search?q1=apple&q2=fruit

在这个 url 中,包含了两个查询参数,q1 和 q2,其中 q1 的值为 apple,q2 的值为 fruit。我们的目标是用 js 解析出 url 所有的查询参数及对应的值。

1、使用 URL 对象的 searchParams

function parseQuery(url) {
    let urlObj = new URL(url);
    return urlObj.searchParams;
}

拿上面的 url 试一试,获取查询参数 q1 的值,使用方法如下:

// 输出: apple
console.log(parseQuery('https://verytools.net/search?q1=apple&q2=fruit').get('q1'));

2、使用原生 JS

如果不借助于 URL 对象,使用原生 js 解析查询参数的思路是截取 url 问号(?)后面的内容,再按照 & 分隔,得到多个查询参数对,每个查询参数对再按照 = 号分割,= 左边的为查询参数,右边的为查询的值。

需要注意的是要使用 decodeURIComponent 还原查询参数的真实值。因为查询参数是 url 的一部分,为确保 url 格式正确,查询参数都是经过编码(encodeURIComponent)后放到 url 中的,因此在解析的时候需要使用 decodeURIComponent 还原查询参数。

function parseQuery(url) {
    let idx = url.indexOf("?");
    let qs = '';
    if (idx !== -1) {
        qs = url.substr(idx + 1);
    }
    if (!qs) {
        return {};
    }
    let ret = {};
    let allQuery = qs.split('&')
    for (let i = 0; i < allQuery.length; i++) {
        let param = allQuery[i];
        let keyValue = param.split('=');
        ret[decodeURIComponent(keyValue[0])] = keyValue[1] ? decodeURIComponent(keyValue[1]) : null;
    }
    return ret;
}

另外需要注意的,该方法没有考虑查询参数中包含锚点(#)的情况,如果需要处理锚点,只需要先将锚点截掉,然后调用该方法即可。使用方法也很简单:

// 输出: apple
console.log(parseQuery('https://verytools.net/search?q1=apple&q2=fruit')['q1']);

删除某个查询参数

有时候我们需要对 url 进行一些处理,删除掉其中某个查询参数,这里分享两种方式。

1、使用 URL 对象

先分享一种简单的方式,借助于 URL 对象的 searchParams,然后使用 searchParams 的 delete 方法删除某个查询参数,最后将 url 对象的各个部分拼接起来即可。实现方法如下:

function removeQuery(url, queryName) {
    let urlObj = new URL(url);
    let queryParams = urlObj.searchParams;
    queryParams.delete(queryName);
    let ret = urlObj.origin + urlObj.pathname;
    let qs = queryParams.toString();
    if (qs) {
        ret += '?' + qs;
    }
    return ret;
}

2、使用原生 JS

function removeQuery(url, queryName) {
    let unifiedUrl = url;
    let idx = url.lastIndexOf('#');
    let anchor = '';
    if (idx !== -1) {
        unifiedUrl = url.substr(0, idx);
        anchor = url.substr(idx)
    }
    idx = unifiedUrl.indexOf("?");
    let base = unifiedUrl;
    let qs = '';
    if (idx !== -1) {
        base = unifiedUrl.substr(0, idx);
        qs = unifiedUrl.substr(idx + 1);
    }
    let params = [];
    if (!qs) {
        return url
    }

    let allQuery = qs.split('&')
    for (let i = 0; i < allQuery.length; i++) {
        let param = allQuery[i];
        if (decodeURIComponent(param.split('=')[0]) !== queryName) {
            params.push(param);
        }
    }
    let ret = base;
    if (params.length > 0) {
        return ret + '?' + params.join("&") + anchor;
    }
    return ret + anchor;
}

让我们删除查询参数 q1 试试:

console.log(removeQuery('https://verytools.net/search?q1=apple&q2=fruit', 'q1'));

输出结果为:https://verytools.net/search?q2=fruit

使用更 modern 的方式

github 上已经有开源库实现了查询参数的处理,库的名字为 qs,仓库地址:https://github.com/ljharb/qs。使用方式很简单:

var qs = require('qs');
var assert = require('assert');
var obj = qs.parse('a=c');
assert.deepEqual(obj, { a: 'c' });
有问题吗?点此反馈!

温馨提示:反馈需要登录