解析 url query 的一些小技巧

2,533 阅读2分钟

大背景

这两天因为要写一个新项目,重拾了 react-router-dom 这个库,但是翻遍了整个文档,居然发现没有 query 解析的功能,唯一擦点边的是 useLocation 这个 api,但是这个返回的是 search 字符串,不是 query 对象,所以解析还得自己来...

正文

秉着 nocode 的工程师精神,我立马去 github 上搜了下相关的库,qs 完美符合

庆祝的表情包_GIF之家

------------------------------------- 分割线 --------------------------------------------

正常开发到这可能就结束了,但是由于这个场景出现的太频繁了(几乎每个项目都会需要解析 url query),于是决定探索一下是否有更好的解决方案。

事情证明它确实存在,那就是: URLSearchParams

用法如下:

const querystring = '?template=1'
// 解析
const query = new URLSearchParams(querystring);
// 获取对应的值
query.get('template');

除了解析 url query 之外,URLSearchParams 还有个很大的使用场景 - 将 query 对象序列化为 url 上的 query 字符串,用法如下:

const query = new URLSearchParams();
// 添加值
query.append('template', 1);
// 获取序列化后的 query 字符串
query.toString(); // "template=1"

再往前一步

前端已经全面进入 ts 时代了,可以通过类型推断来极大的提升开发体验。上面返回的 query 有个小问题, query.get('xxx') 参数可以填任意字符串,开发中容易出现 typo,也不易于后期维护。我们希望的效果应该是下面这样的,调用 query.get() 的时候,智能提示我们有哪些参数可用,并且会在碰到无效参数时报编译错误:

直接上代码:

function parseQuery<T extends Record<string, any>, K = keyof T>(queryStr: string) { 
    const query = new URLSearchParams(queryStr);  
    return {    
        get(name: K) {      
            // @ts-ignore      
            return query.get(name);    
        }  
    }
}

interface Query {  
    template: string;
}

const query = parseQuery<Query>('template=1');
query.get('template'); // √
query.get('id'); // ×

总结

1. query 的解析可以直接使用 URLSearchParams

2. 基于 ts 做一层类型封装,提高开发体验以及降低维护成本