useURLQuery
该函数允许您轻松地获取和设置URL查询参数,在响应式数据变化时,自动更新查询参数,在查询参数变化时,自动更新响应式数据。
为什么不使用
vueuse的useRouteQuery?因为vueuse的useRouteQuery会在query变化时,会更新整个网站使用useRouteQuery定义的变量(spa)。而useURLQuery只会更新当前页面组件的变量。
实现源码
ts
import { ref, watch, computed, nextTick, type Ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
type IQuery = string | number | string[] | null | undefined;
const queriesQueue = new Map<string, Record<string, IQuery>>();
export const useURLQuery = <T extends IQuery, K extends IQuery = T>(
name: string,
defaultValue?: T,
options: {
transform?: (value: any) => K;
mode?: 'push' | 'replace';
isEncodeURIComponent?: boolean;
} = {}
) => {
const {
mode = 'push',
transform = (value) => value,
isEncodeURIComponent = false
} = options;
const route = useRoute();
const router = useRouter();
const currentPath = route.path;
const query = ref(defaultValue) as Ref<T | K>;
watch(
() => route.query[name],
(value) => {
if (route.path !== currentPath) {
return;
}
if (value === undefined) {
query.value = defaultValue as T;
return;
}
if (!isEncodeURIComponent) {
query.value = transform(value);
return;
}
query.value = transform(decodeURIComponent(value as string));
},
{ immediate: true }
);
const setQueryQueue = (value: IQuery) => {
const currentPageQueries = queriesQueue.get(currentPath) || {};
if (value === null || value === undefined || !isEncodeURIComponent) {
currentPageQueries[name] = value;
} else {
currentPageQueries[name] = encodeURIComponent(value as string);
}
queriesQueue.set(currentPath, currentPageQueries);
};
watch(query, (value) => {
setQueryQueue(value as IQuery);
nextTick(() => {
const currentPageQueries = queriesQueue.get(currentPath) || {};
const { params, query: oldQuery, hash } = route;
router[mode]({
params,
query: {
...oldQuery,
...currentPageQueries
},
hash
});
});
});
return query;
};
export const useURLQueryObject = <T extends Record<string, any>>(
name: string,
defaultValue?: T,
options: {
transform?: (value: string | undefined) => string;
mode?: 'push' | 'replace';
isEncodeURIComponent?: boolean;
} = {}
) => {
const str = useURLQuery<string | undefined>(name, undefined, options);
const search = computed({
get: () => {
try {
return str.value !== undefined ? JSON.parse(str.value) : defaultValue;
} catch (error) {
return defaultValue;
}
},
set: (val: T) => {
try {
str.value = val !== undefined ? JSON.stringify(val) : undefined;
} catch (error) {
str.value = undefined;
}
}
});
if (defaultValue !== undefined) {
search.value = defaultValue;
}
return search;
};介绍
本文 useURLQuery 是基于vue-router的useRoute实现的,因此可以在任何需要获取和设置URL查询参数的地方使用。
该函数接收三个参数:
name字符串类型,查询参数的名称;defaultValue可选参数,任意类型,查询参数的默认值;options可选参数,对象类型,包含transform、mode、isEncodeURIComponent三个可选属性:transform转换函数,用于转换查询值的类型;mode路由模式,可选值push与replace,用于控制查询参数的更新方式;isEncodeURIComponent布尔类型,是否对查询参数进行编码。
使用
vue
<template>
<input v-model="name" />
</template>
<script setup>
import { useURLQuery } from 'useURLQuery.ts'
// 获取查询参数name,如果没有则使用默认值default
// 当name变化时,会自动更新查询参数,例如:http://localhost:8080/?name=xxx
const name = useURLQuery('name', 'default')
</script>