从url的query中取值

7 阅读3分钟

一、URL Query的基础概念

URL的query(查询字符串)是URL中?之后的部分,用于传递参数,格式为key=value&key2=value2。例如:

https://example.com/path?name=张三&age=25&hobbies=reading,music

核心需求:从URL中解析出这些参数,用于前端路由、数据筛选或接口请求。

二、原生JavaScript解析方法

1. 使用URLSearchParams(ES6+推荐方案)

// 解析当前页面URL的query
const url = new URL(window.location.href);
const params = new URLSearchParams(url.search);

// 获取单个参数
const name = params.get('name'); // "张三"
const age = params.get('age');   // "25"

// 获取多个同名参数(如hobbies)
const hobbies = params.getAll('hobbies'); // ["reading", "music"]

// 转换为对象
const paramsObj = Object.fromEntries(params.entries());
// { name: "张三", age: "25", hobbies: "reading,music" }

// 检查参数是否存在
params.has('age'); // true

2. 手动解析字符串(兼容旧浏览器)

function getQueryParams(url = window.location.href) {
  const search = url.split('?')[1];
  if (!search) return {};
  
  const params = {};
  search.split('&').forEach(param => {
    const [key, value] = param.split('=');
    if (key) {
      // 解码URI编码(如%20转空格)
      params[key] = decodeURIComponent(value || '');
    }
  });
  return params;
}

// 使用示例
const params = getQueryParams();
console.log(params.name); // "张三"
console.log(params.hobbies); // "reading,music"

三、框架与库的解析方案(工程实践)

1. React Router解析(常用场景)

import { useLocation } from 'react-router-dom';

function MyComponent() {
  const location = useLocation();
  const searchParams = new URLSearchParams(location.search);
  
  // 获取参数
  const page = searchParams.get('page') || 1;
  const keyword = searchParams.get('keyword') || '';
  
  return (
    <div>
      页码: {page}, 关键词: {keyword}
    </div>
  );
}

2. Vue Router解析(Vue 3示例)

<template>
  <div>
    <p>ID: {{ id }}</p>
    <p>搜索词: {{ keyword }}</p>
  </div>
</template>

<script setup>
import { useRoute } from 'vue-router';

const route = useRoute();
const id = route.query.id;
const keyword = route.query.keyword || '默认搜索词';
</script>

3. 第三方库(如qs)

import qs from 'qs';

// 解析query字符串
const search = window.location.search.slice(1); // 去除?
const params = qs.parse(search, {
  ignoreQueryPrefix: true,
  decode: true
});

// 处理数组参数(如hobbies=reading&hobbies=music)
const hobbies = params.hobbies || [];

四、问题

1. 问:如何处理query中的数组参数?

    1. URLSearchParams.getAll()
      // URL: ?hobbies=reading&hobbies=music
      const hobbies = params.getAll('hobbies'); // ["reading", "music"]
      
    2. 自定义解析规则
      若参数格式为?hobbies=reading,music,可通过逗号分割:
      const hobbies = (params.hobbies || '').split(',');
      
    3. 第三方库支持
      qs库可自动解析数组参数(需配置arrayFormat: 'repeat')。

2. 问:如何处理URI编码的参数?

    • 编码场景:参数包含特殊字符(如空格、中文)时会被编码为%20%E4%B8%AD%E6%96%87
    • 解码方法
      • decodeURIComponent(params.get('key')):解码单个参数
      • 手动解析时使用decodeURIComponent(value)(如前文手动解析函数)

3. 问:前端路由如何与query参数联动?

    • React场景
      // 跳转时携带query参数
      history.push({
        pathname: '/search',
        search: `?keyword=${encodeURIComponent('前端')}&page=2`
      });
      
      // 或使用useSearchParams Hook(React Router 6+)
      import { useSearchParams } from 'react-router-dom';
      
      function SearchPage() {
        const [searchParams, setSearchParams] = useSearchParams();
        searchParams.set('page', '2');
        setSearchParams(searchParams);
      }
      
    • Vue场景
      // 编程式导航携带query
      this.$router.push({
        path: '/search',
        query: { keyword: '前端', page: 2 }
      });
      

五、实战场景与边界处理

1. 动态生成带query的URL

// 场景:搜索条件变化时更新URL
function updateUrlWithParams(params) {
  const url = new URL(window.location.href);
  Object.keys(params).forEach(key => {
    if (params[key] !== undefined) {
      url.searchParams.set(key, params[key]);
    } else {
      url.searchParams.delete(key); // 删除未定义的参数
    }
  });
  window.history.pushState(null, '', url.href);
}

// 使用示例
updateUrlWithParams({ keyword: '性能优化', page: 3 });

2. 处理多级嵌套参数

// URL: ?user[name]=张三&user[age]=25
function parseNestedParams(params) {
  const result = {};
  for (const [key, value] of params.entries()) {
    let current = result;
    const keys = key.split('[');
    
    // 处理最后一个键(可能带])
    const lastKey = keys.pop().replace(']', '');
    
    // 构建嵌套对象
    keys.forEach(k => {
      if (!current[k]) current[k] = {};
      current = current[k];
    });
    
    current[lastKey] = value;
  }
  return result;
}

const nestedParams = parseNestedParams(params);
// { user: { name: "张三", age: "25" } }

六、总结

“从URL的query中取值可分为三类方案:

  1. 原生JS:使用URLSearchParams(ES6+)或手动解析字符串,前者支持数组参数和便捷API;
  2. 框架集成:React Router用useLocation,Vue Router用$route.query,适配路由场景;
  3. 第三方库:如qs库支持嵌套参数解析和编码处理。

实际项目中,我会根据场景选择方案:简单场景用原生URLSearchParams,复杂参数处理用qs库,路由联动则优先使用框架提供的API。同时需注意URI编码/解码、数组参数处理和历史记录更新,确保参数解析的准确性和用户体验的一致性。”