在 Vue 项目中使用 URL Query 保存和恢复搜索条件


在 Vue 项目中使用 URL Query 保存和恢复搜索条件

在实际的前端开发中,我们经常会遇到这样的需求:

用户在列表页输入了一些搜索条件,点击某一条数据进入详情页;当他返回列表页时,希望搜索条件能被 记住,而不是重新初始化。

常见的解决方案有三种:

  1. 使用 全局状态管理(Vuex/Pinia) 保存搜索条件。
  2. 使用 keep-alive 缓存页面组件。
  3. 使用 URL Query 参数 把搜索条件保存在地址栏中。

本文介绍的是第三种方式,通过封装一个 useQueryStorage Hook,把对象序列化到 URL 的 querystring 中,从而实现搜索条件的记忆。


核心代码

ini 复制代码
import { isEqual } from "lodash-es";
import { useRouter, useRoute } from "vue-router";

export const useQueryStorage = <T>(key: string = "savedQuery") => {
  const router = useRouter();
  const route = useRoute();

  // 把对象以 JSON 的格式存入到 URL 的 querystring 中
  const saveObjectToQueryString = (obj: T) => {
    const query = parseSavedObjectFromQueryString();
    if (!isEqual(query, obj)) {
      router.replace({
        query: {
          ...route.query,
          [key]: encodeURIComponent(JSON.stringify(obj)),
        },
      });
    }
  };

  // 从 URL 的 querystring 中解析出对象
  const parseSavedObjectFromQueryString: () => T | null = () => {
    let query = route.query[key];
    if (query && typeof query === "string") {
      query = JSON.parse(decodeURIComponent(query));
      return query as T;
    }
    return null;
  };

  return {
    getQ: parseSavedObjectFromQueryString,
    setQ: saveObjectToQueryString,
  };
};

代码解析

1. 存储对象到 URL

ini 复制代码
const saveObjectToQueryString = (obj: T) => {
  const query = parseSavedObjectFromQueryString();
  if (!isEqual(query, obj)) {
    router.replace({
      query: {
        ...route.query,
        [key]: encodeURIComponent(JSON.stringify(obj)),
      },
    });
  }
};

这里使用了 JSON.stringify 把对象转成字符串,再用 encodeURIComponent 确保字符串在 URL 中不会出错。

为什么要用 lodash.isEqual

👉 因为 Vue Router 的 replace 会更新 URL,如果我们每次都写入同样的对象,就会产生冗余的路由更新。用 isEqual 做深度比较,可以避免不必要的刷新。


2. 从 URL 解析对象

ini 复制代码
const parseSavedObjectFromQueryString: () => T | null = () => {
  let query = route.query[key];
  if (query && typeof query === "string") {
    query = JSON.parse(decodeURIComponent(query));
    return query as T;
  }
  return null;
};

这一段逻辑就是把 querystring 里的值取出来,做 解码 + JSON 反序列化,还原成原来的对象。


3. Hook 的返回值

kotlin 复制代码
return {
  getQ: parseSavedObjectFromQueryString,
  setQ: saveObjectToQueryString,
};

对外提供两个方法:

  • getQ():获取保存的搜索条件。
  • setQ(obj):设置搜索条件并保存到 URL。

这样调用方的代码就会非常简洁。


使用示例

在列表页中:

ini 复制代码
const { getQ, setQ } = useQueryStorage<{ keyword: string; page: number }>();

// 初始化时恢复
const saved = getQ();
if (saved) {
  searchForm.keyword = saved.keyword;
  searchForm.page = saved.page;
}

// 用户点击搜索时保存
function handleSearch() {
  setQ({ keyword: searchForm.keyword, page: searchForm.page });
}

当用户进入详情页再返回时,URL 中依然保存了搜索条件,页面加载时会自动恢复。


优点总结

  1. 刷新不丢失
    因为状态存放在 URL 里,刷新后依然可以恢复。
  2. 可分享链接
    用户可以直接复制 URL,别人打开时能看到相同的搜索条件。
  3. 解耦全局状态
    不依赖 Vuex/Pinia,逻辑简单清晰。

缺点是:如果搜索条件非常复杂,URL 会变长,可能不太美观。


总结

useQueryStorage 是一个非常实用的小 Hook,通过 encodeURIComponentJSON.stringify 将对象持久化到 URL 的 query 参数中,结合 lodash.isEqual 避免重复写入,能很好地解决 列表页返回时记住搜索条件 的问题。

相关推荐
跳动的梦想家h17 分钟前
环境配置 + AI 提效双管齐下
java·vue.js·spring
冰暮流星39 分钟前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_1 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js
一 乐2 小时前
校园二手交易|基于springboot + vue校园二手交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端
科技D人生2 小时前
Vue.js 学习总结(20)—— Vue-Office 实战:word、pdf、excel、ppt 多种文档的在线预览
vue.js·word·vue-pdf·stylesheet·docx-preview·vue-office
vx1_Biye_Design2 小时前
基于Spring Boot+Vue的学生管理系统设计与实现-计算机毕业设计源码46223
java·vue.js·spring boot·spring·eclipse·tomcat·maven
vx_Biye_Design2 小时前
基于Spring Boot+vue的湖北旅游景点门票预约平台的设计--毕设附源码29593
java·vue.js·spring boot·spring cloud·servlet·eclipse·课程设计
hedley(●'◡'●)2 小时前
基于cesium和vue的大疆司空模仿程序
前端·javascript·vue.js·python·typescript·无人机
qq5_8115175152 小时前
web城乡居民基本医疗信息管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
百思可瑞教育2 小时前
构建自己的Vue UI组件库:从设计到发布
前端·javascript·vue.js·ui·百思可瑞教育·北京百思教育