前言
工作时候遇到想要把请求的参数添加到url中,以便别人通过携带参数的url地址直接访问并根据参数选好对应的选项。
自己去处理把参数通过js方法变化到一定格式添加到url地址中,再自己去一步步去解析还原到自己想要的数据结构。
这样对于简单的数据结构来说是轻易可以做到的,但是如果数据结构比较复杂的情况就比较复杂了
一:QS简介
QS库是一种用于处理URL查询字符串(Query String)的工具库,主要用于前端开发中。URL查询字符串是URL中问号后面的部分,通常包含各种参数和其对应的值。
二:导入QS
方式一:HTML中导入
可以使用在Web上托管的QS库的CDN链接。将以下代码添加到HTML文件中,即可使用CDN导入
js
<script src="https://cdn.bootcdn.net/ajax/libs/qs/6.10.1/qs.js"></script>
js
let qs = Qs
console.log(qs)
方式二:npm包
-
a. 在终端中运行以下命令安装QS库:
jsnpm install qs
b. 在你的JavaScript文件中导入QS库:
js// 例如,使用ES6模块的导入语法 import qs from 'qs';
或者,如果你使用CommonJS:
jsconst qs = require('qs'); ```。
一旦你导入了QS库,你就可以在你的JavaScript代码中使用它来处理URL参数了。例如:
js
const parsedParams = qs.parse(window.location.search, { ignoreQueryPrefix: true });
console.log(parsedParams);
上述代码将解析当前页面的URL查询字符串并将其作为JavaScript对象打印出来
三:使用
1.parse解析
使用 QS 库的 parse
方法可以将 URL 查询字符串解析为 JavaScript 对象。例如:
js
const qs = require('qs');
const queryString = 'name=John&age=30&gender=male';
const parsedParams = qs.parse(queryString);
console.log(parsedParams);
输出
js
{
name: 'John',
age: '30',
gender: 'male'
}
2. stringify序列化
使用 QS 库的 stringify
方法可以将 JavaScript 对象序列化为 URL 查询字符串。例如:
js
const qs = require('qs');
const params = {
name: 'John',
age: 30,
gender: 'male'
};
const queryString = qs.stringify(params);
console.log(queryString);
输出
js
name=John&age=30&gender=male
qs.stringify
方法默认使用 &
作为参数之间的分隔符,可以根据需要进行配置。
3. 配置项
delimiter
: 指定用于分隔参数的字符串,默认为'&'
。
js
const queryString = 'name=John,age=30,gender=male';
const parsedParams = qs.parse(queryString, { delimiter: ',' });
arrayFormat
: 控制序列化数组的方式,可选值有'indices'
(默认,通过添加索引来表示数组)、'brackets'
(使用方括号表示数组)和'repeat'
(重复参数名称表示数组)。
js
const params = { colors: ['red', 'green', 'blue'] };
const queryString = qs.stringify(params, { arrayFormat: 'brackets' });
encode
: 指定是否对参数进行URL编码,默认为true
。
js
const params = { name: 'John Doe' };
const queryString = qs.stringify(params, { encode: false });
decode
: 指定是否对解析后的参数进行URL解码,默认为true
。
js
const queryString = 'name=John%20Doe';
const parsedParams = qs.parse(queryString, { decode: false });
allowDots
: 指定是否允许在参数名称中使用点号.
,默认为false
。如果设置为true
,则可以处理嵌套的对象。
js
const params = { user: { name: 'John', age: 30 } };
const queryString = qs.stringify(params, { allowDots: true });
ignoreQueryPrefix
: 指定是否忽略查询字符串的前缀(通常是?
),默认为false
。
js
const queryString = '?name=John&age=30';
const parsedParams = qs.parse(queryString, { ignoreQueryPrefix: true });
四:具体场景
提出需求(万恶源头)...
某个查询界面,把查询请求参数,添加到url地址中,但是这个参数很多也很复杂,包括各种select框等等。
别人可以根据url地址中的参数,跳转到对应页面并且根据参数直接把select,input等相关选项选好
对于不选的选项,为空值,但是要保证url地址的美观...
序列化过程...
在某个查询界面,查询参数比较多,数据结构是嵌套的使用,有的选项也不必选就默认值为null,select不选数组就是空值。
对于这些空值就需要对这个数据结构过滤处理,这样添加到url太过冗余了。
原始数据类型,空数组,空对象就不需要被序列化。
举例
js
let qs = Qs
const complexDataStructure = {
name: 'John Doe',
age: 30,
address: {
street: '123 Main St',
city: 'Anytown',
country: 'USA',
tags: []
},
isStudent: false,
grades: [90, 85, 92],
metadata: {
preferences: {
theme: 'dark',
fontSize: 16
}
},
emptyArray: [],
emptyObject: {},
nullableValue: null
}
console.log(qs.stringify(complexDataStructure))
name=John%20Doe&age=30&address%5Bstreet%5D=123%20Main%20St&address%5Bcity%5D=Anytown&address%5Bcountry%5D=USA&isStudent=false&grades%5B0%5D=90&grades%5B1%5D=85&grades%5B2%5D=92&metadata%5Bpreferences%5D%5Btheme%5D=dark&metadata%5Bpreferences%5D%5BfontSize%5D=16&nullableValue=
太过冗余了,需要过滤一下
过滤空值...
过滤函数
js
const filterValues = function (obj) {
const filteredObj = {}
for (const key in obj) {
const value = obj[key]
if (Array.isArray(value)) {
// 处理数组
if (value.length > 0) {
filteredObj[key] = value
}
} else if (value !== null && value !== '') {
if (typeof value === 'object') {
// 递归处理嵌套对象
const nestedFiltered = filterValues(value)
if (Object.keys(nestedFiltered).length > 0) {
filteredObj[key] = nestedFiltered
}
} else {
filteredObj[key] = value
}
}
}
return filteredObj
}
// 获取过滤后的数据
const filteredData = filterValues(complexDataStructure)
console.log(filteredData)
把空值和空数组过滤掉了,这下再序列化就不会那么冗余了
js
{
"name": "John Doe",
"age": 30,
"address": {
"street": "123 Main St",
"city": "Anytown",
"country": "USA"
},
"isStudent": false,
"grades": [
90,
85,
92
],
"metadata": {
"preferences": {
"theme": "dark",
"fontSize": 16
}
}
}
一般把这个函数添加到请求前面即可...
序列化 + 拼接url
js
const queryString = qs.stringify(filteredData)
let url = new URL(window.location.href)
const baseUrl = url.origin + url.pathname
const fullUrl = baseUrl + '?' + queryString
window.history.replaceState({}, '', fullUrl);
//
http://127.0.0.1:5500/qs.html?name=John%20Doe&age=30&address%5Bstreet%5D=123%20Main%20St&address%5Bcity%5D=Anytown&address%5Bcountry%5D=USA&isStudent=false&grades%5B0%5D=90&grades%5B1%5D=85&grades%5B2%5D=92&metadata%5Bpreferences%5D%5Btheme%5D=dark&metadata%5Bpreferences%5D%5BfontSize%5D=16
模拟用户重新选择选项,修改数据
js
complexDataStructure.age = 50
complexDataStructure.nullableValue = true
complexDataStructure.grades = [0, 0, 0]
complexDataStructure.metadata.preferences.theme = '0'
这里用户修改完数据后,重新打请求url地址参数也就会再次变化
解析 + 还原...
由于需求是别人通过你的url中的参数,可以直接选择好对应的选项并查询。
但是由于还要考虑url参数美观,我们过滤掉了空数组,空对象等。
那么对于select组件就一定会报错,空数组没有length长度等问题。
因此我们还要把原先的空值再给他还原回去...但如果创建新对象去处理就比较复杂了
直接跟原先数据结构进行对比,没有的字段直接用原先的就好了
解析 + 比对
js
const currentUrl = window.location.href
const params = currentUrl.split('?')[1]
const parsedData = qs.parse(params)
if (params) {
try {
for (const key in parsedData) {
if (parsedData.hasOwnProperty(key)) {
// 如果解析出来的值不为 null 或空字符串,更新 complexDataStructure
if (parsedData[key] !== null && parsedData[key] !== '') {
complexDataStructure[key] = parsedData[key]
}
}
}
} catch (error) {
console.error('Error parsing JSON:', error)
}
}
console.log(complexDataStructure)
这个过程就是把修改的数据再填到原先的数据结构
complexDataStructure
中,这样子空值咱们就完全不用管了
js
{
"name": "John Doe",
"age": "50",
"address": {
"street": "123 Main St",
"city": "Anytown",
"country": "USA"
},
"isStudent": "false",
"grades": [
"0",
"0",
"0"
],
"metadata": {
"preferences": {
"theme": "0",
"fontSize": "16"
}
},
"emptyArray": [],
"emptyObject": {},
"nullableValue": "true"
}
这样子用户根据url参数跳转过去,直接就根据参数选好了,url参数也过滤了,属于是非常美观了...
那么结果也就very biu特佛了...