React中URL参数重复编码导致JS无法识别参数相等问题
React商城筛选功能中URL参数重复编码导致参数无法识别的问题
我用React实现商城商品筛选功能,用户选择筛选项时,通过onChange事件将筛选项名称和值编码后存入URL查询参数。大部分参数正常工作,但当筛选项名称为“With Usb 3 Ports”时出现异常:存入URL后参数变为With%2520USB%25203%2520ports=Yes,尝试将值改为“No”时,JS无法识别URL中的该参数与目标参数相等,导致重复新增参数而非更新。用到的技术包括window.location.search、encodeURIComponent、URLSearchParams、window.location.href跳转,相关代码如下:
//* Change the url params when the user changes the filter inputs changeUrlParam = () => { //* Prepare localhost variable const baseUrl = 'http://localhost:3000' //* Get current path name const pathName = window.location.pathname; //* Get current url parameters if any const urlQuery = window.location.search; const pureParam = urlQuery.replace('?', ''); //* Create a new param const params = urlQuery.length < 1 ? new URLSearchParams() : new URLSearchParams(pureParam); //* Prepare the value/key pair const key = encodeURIComponent('With Usb 3 Ports'); const value = 'Yes'; //* If the params - ARE NOT SET if(urlQuery.length < 1) { //* Apend new value to it params.append(key, value); //* If the params - ARE SET } else { //* Check if the param in question is already set const paramTest = urlQuery.includes(key); //* If present - change it if(paramTest === true) { //* Change the old value to the new value params.set(key, value); //* If not present - apend it } else { //* Add the new value to the exsisting param params.append(key, value); } } //* Prepare the new url const newUrl = baseUrl + pathName + '?' + params.toString(); //* Go to the new url return window.location.href = newUrl; };
原因分析
- 重复编码问题:你手动用
encodeURIComponent编码了键名,但URLSearchParams的append/set方法会自动对键和值进行URL编码。这导致空格先被编码为%20,之后又被二次编码为%2520(%字符会被编码成%25),最终URL中的参数名变成了With%2520USB%25203%2520ports。 - 参数判断逻辑错误:你用
urlQuery.includes(key)检查参数是否存在,但urlQuery是原始的URL查询字符串(包含二次编码后的内容),而key是仅经过一次编码的字符串,两者无法匹配,导致每次都会执行append而非set。
解决方案
修改要点
- 移除手动对键名的
encodeURIComponent编码,让URLSearchParams自动处理编码,避免二次编码。 - 改用
URLSearchParams的has方法检查参数是否存在,它能自动处理编码后的键名匹配,无需操作原始查询字符串。 - 简化
URLSearchParams的初始化逻辑,直接传入window.location.search即可,无需手动去除开头的?。
修改后的代码
changeUrlParam = () => { const baseUrl = 'http://localhost:3000'; const pathName = window.location.pathname; // 直接用window.location.search初始化,URLSearchParams会自动处理开头的? const params = new URLSearchParams(window.location.search); // 使用原始键名,无需手动编码 const key = 'With Usb 3 Ports'; const value = 'Yes'; // 用URLSearchParams内置的has方法检查参数是否存在 if (params.has(key)) { params.set(key, value); } else { params.append(key, value); } const newUrl = `${baseUrl}${pathName}?${params.toString()}`; window.location.href = newUrl; };
内容的提问来源于stack exchange,提问作者ghost
相关产品推荐
相关产品推荐

