4. 通过查询字符串传递参数

查询字符串(Query String)是 URL 中 ? 后的键值对序列,在前端路由传参中最常见。本章讲解三种传参方式:手写拼接、使用 URLSearchParams 对象、处理多参数与可选参数,并覆盖调试、部署、常见错误与性能优化。

4.1 原理与实现流程

浏览器向服务器或 SPA 路由发送请求时,将查询参数附加在 URL 尾部。前后端均可通过解析该字符串获取参数。核心流程如下:

  • 构造 URL:在基础路径后添加 ? 开始查询部分。
  • 拼接键值对:key=value 形式,多参数间用 & 连接。
  • 编码:特殊字符(空格、中文、符号)必须进行百分号编码。
  • 传递:发起请求(fetch、XMLHttpRequest 或直接导航)。
  • 解析:服务端或客户端通过 URLSearchParams 或正则提取参数。
关键区别:手动拼接适合极简场景,但容易遗漏编码或引入错误;URLSearchParams 提供标准化的增删改查,自动编码,推荐用于现代应用。
提示:在 SPA 路由(如 React Router / Vue Router)中,查询参数通常由 useSearchParams() 或 $route.query 自动管理,但底层依然是 URLSearchParams。
查询参数传递流程 查询参数传递流程 浏览器 URL 识别 ? 开始查询 编码 & 拼接 使用 URLSearchParams 自动编码 / 添加 / 删除 手动字符串拼接 需自行 encodeURIComponent 多参数 & 可选参数处理 发起请求 / 导航 推荐使用 URLSearchParams

4.2 实现步骤与代码

4.2.1 手动拼接查询字符串(传统方式)

// 基础 URL
const baseUrl = 'https://api.example.com/search';
// 手动拼接
const query = '?q=JavaScript&page=1&limit=10';
const fullUrl = baseUrl + query;
注意:手工拼接极易忽略编码。若参数值包含 &、?、空格或中文,必须使用 encodeURIComponent() 对每个值进行编码。
const q = 'JS & TS';
const page = 1;
const safeQuery = '?q=' + encodeURIComponent(q) + '&page=' + page;
// 结果: ?q=JS%20%26%20TS&page=1

4.2.2 使用 URLSearchParams(推荐)

const params = new URLSearchParams();
params.append('q', 'JavaScript');
params.append('page', '1');
params.append('limit', '10');

const url = `/search?${params.toString()}`;
// 输出: /search?q=JavaScript&page=1&limit=10

URLSearchParams 自动对键和值进行百分号编码,无需手动处理。

4.2.3 多参数处理

同一个键允许出现多次(例如多选过滤)。URLSearchParams 原生支持重复键:

const params = new URLSearchParams();
params.append('tag', 'javascript');
params.append('tag', 'typescript');
params.append('tag', 'react');

console.log(params.toString());
// "tag=javascript&tag=typescript&tag=react"

// 获取所有 tag
console.log(params.getAll('tag'));
// ["javascript", "typescript", "react"]

4.2.4 可选参数处理

当参数存在时才添加到查询字符串中,避免出现 key=undefined 或空值:

function buildSearchUrl(base, { q, page, limit, sort }) {
  const params = new URLSearchParams();
  if (q) params.append('q', q);
  if (page !== undefined) params.append('page', page);
  if (limit !== undefined) params.append('limit', limit);
  if (sort) params.append('sort', sort);

  const queryString = params.toString();
  return queryString ? `${base}?${queryString}` : base;
}

// 使用示例
console.log(buildSearchUrl('/search', { q: 'JS', page: 1 }));
// "/search?q=JS&page=1"

console.log(buildSearchUrl('/search', {}));
// "/search"

4.3 调试方法

  1. 浏览器 DevTools → Network 面板:查看请求 URL,确认查询字符串是否正确。
  2. 控制台打印 params.toString():验证编码结果。
  3. 使用 URL 对象解析:
const url = new URL('https://example.com/search?q=hello&page=1');
console.log(url.searchParams.get('q'));  // "hello"
console.log(url.searchParams.has('page')); // true

4.4 部署注意事项

注意事项 说明
URL 长度限制 查询字符串通常限制在 2048~4096 字节(浏览器 / 服务器)。大量参数应使用 POST 请求体传递。
编码一致性 服务端与客户端需使用相同编码(通常 UTF-8)。前端 URLSearchParams 默认使用 UTF-8。
敏感数据 查询字符串会出现在浏览器历史、服务器日志中,切勿传递密码、 等敏感信息。
跨域 CORS 查询参数本身不影响 CORS,但请求 URL 需在允许的原名单内。

4.5 常见错误与排查

  • 忘记编码:参数值含 & 导致解析错误 → 使用 encodeURIComponent 或 URLSearchParams。
  • 重复参数覆盖:手动拼接时误用 = 而非 & → 使用 append 而非 set。
  • 可选参数判断不严谨:if (page) 当 page=0 时被跳过 → 应使用 if (page !== undefined)。
  • 空字符串保留:传 key= 而非完全省略 → 使用 if (val !== '') 控制。

4.6 性能与稳定性优化

  • 缓存参数序列化结果:对于固定参数(如分页),可缓存 params.toString() 避免重复构建。
  • 避免无效参数:构建前过滤掉 null、undefined、空字符串,缩短 URL 长度。
  • 使用 URL 对象代替手动拼接:更稳定,自动处理基路径与查询字符串的拼接。
  • 批量操作时考虑 sort() 方法:params.sort() 可对参数键排序,提升缓存命中率。
// 性能优化示例:缓存序列化结果
const params = new URLSearchParams({ q: 'hello', page: 1 });
const cachedQuery = params.toString(); // 只计算一次
// 后续请求直接复用 cachedQuery
稳定性提示:在 Node.js 服务端解析查询字符串时,避免使用 querystring 旧模块,推荐使用 URLSearchParams(全局可用)或 new URL(url).searchParams。