vue实现前端保持筛选条件到url并进行同步参数设计

 更新时间:2022年8月11日 13:47  点击:564 作者:daisY

前言

在有列表页的系统中,常常为了提高用户体验,需要保持列表页的筛选条件、分页情况。需要做到刷新页面,从详情页返回列表页保留之前的筛选情况。你可能会说 vue 用 keep-alive 缓存列表页不就行了?为什么不好呢?

因为正确的做法是将筛选条件保存在 url 上,这样可以复制给别人直接使用,并且你可以看到几乎所有网站都是使用这种方法。接下来会带大家了解有关 url 参数的基础知识和设计思路。并且封装成了一个 hook vue-use-sync-url,欢迎在你的项目中直接使用。

基础知识

假设 url 上的参数为 ?a=1&a=2&b=true,来看看获取参数的方法

const searchParams = new URLSearchParams(window.location.search);
// ["1", "2"]
searchParams.getAll("a");
// "1"
searchParams.get(a);
// ["true"]
searchParams.getAll(b);
// "true"
searchParams.get(b);

添加

searchParams.append("a", "1");
searchParams.append("a", "2");
// ?a=1&a=2
searchParams.set("b", "3");
searchParams.set("b", "4");
// ?b=4

从上面的结果可以得知,无论什么值最后都会被解析成 string 类型, 如果存在两个名字相同的 key,则会被解析为 string[]。 所以从 url 参数获取到的类型只会为 string | string[]

最后使用 history.pushState 来修改浏览器地址栏的 url 参数。与 history.replaceState 不同的是,一个是添加一条新记录,一个是替换。在这里我们当然是选择添加新记录了。

设计思路

首先肯定要知道哪些值需要同步到 url 参数上,所以我们定义了一个 configs 参数,来配置需要同步的值。类型为数组,这样可以让用户自定义顺序,每项需要传入一个 key 值。

hook 内部返回一个 syncToUrl 方法,传入包含配置的所有 key 的值。用户可以在自己需要的时候同步 url。

const { syncToUrl } = useSyncUrl({
  configs: [{ key: "title" }, { key: "status" }]
})
// 同步
syncToUrl(values)

假设 title 与输入框绑定,且没有值,传入 syncToUrl 的是 "",这就没有必要同步到 url 上了。所以我们添加一个配置 omitEmptyString,如果值为空字符串,则忽略。

[{ key: "title", omitEmptyString: true }]

同理,可以增加 omitNullomitUndefined。这三个默认都设为 true

接下来,我们先明白两个概念。在页面第一次加载、执行浏览器前进回退操作时,需要将 url 参数的值转换到当前页面的组件中,在这里我们称其为 decode

在页面中筛选结束点击提交或切换页码时,需要将这些值转换成参数并设置到 url 的参数上,在这里我们称其为 encode

decode

了解后,我们就可以知道上面例子中 key: "status",可以想成是一个 Select 组件,值为 boolean 类型。从基础知识可以得知,从 url 取下来的值为 string 类型。 需要使用 decode 转换成 boolean 类型。

const values = reactive({ title: "", status: false });
const booleanValues = {
  true: true,
  false: false,
}
const { syncToUrl } = useSyncUrl({
  configs: [
    {
      // title 的值是字符串类型,所以不需要 decode
      key: "title",
    },
    { 
      key: "status", 
      // 参数是从 url 上 key 为 status 的值
      decode: (value) => booleanValues[value] 
    }
  ],
  onDecode: (params) => {
    Object.keys(params).forEach(key => {
        values[key] = params[key]
    });
    // 设置完成后,在这里请求数据
  }
})

decode 中,我们将值 return 出去,在 onDecode 中将每个配置项返回的值统一收集起来,设置完成后,请求列表数据。像 title 这种值本身是字符串的就不用写 decode。假设 url 上的参数为 ?title=11&status=true,这里的 params 的值就为

{
  title: "11",
  status: true
}

decode 也可以返回一个对象,如果是对象也会被收集到 onDecode 中。如果不想被收集,可以返回空对象 {}。所以如果你想在 decode 中进行赋值也可以,但要返回 {}

decode: (value) => {
  return {
    a: "1",
    b: "2"
  }
}
// 不会被收集
decode: (value) => {
  return {};
}

encode

const values = reactive({ rangeDate: ["2022-10-1", "2022-10-2"] });
useSyncUrl({
  configs: [
   {
     key: "rangeDate",
     encode: (value) => {
       return {
         starDate: value[0],
         endDate: value[1]
       }
     }
   }
  ]
})

encode 可以将值转换成你想要的格式同步到 url 上。这个例子中如果不写 encode,通过了解上面的基础知识,则会被转换成两个 rangeDate 的键值对。这里自定义转换成了 starDate 和 endDate。所以还要配合 decode 使用。

decode: (value) => ...

但是这个 value 返回的是 url 上 key 为 "rangeDate" 的值,我们要怎么 decode starDate 和 endDate 呢?所以增加一个配置项 decodeKeys 来实现。。

{
 key: "rangeDate",
 decodeKeys: ["starDate", "endDate"],
 decode: value => {
   return {
     rangeDate: [value.starDate, value.endDate]
   }
 }
}

通过上面基础知识可以得知,url 的值只能为 string | string[],所以 encode 返回的值也只能是 EncodeResult | Record<string, EncodeResult>。内部将 numberboolean 转换成了 string

type EncodeResult = string | number | boolean | (string | number | boolean)[];

这时候就有问题了,我想将一个比较复杂类型的值同步到 url 上怎么办?这时候就要用到 encodeURIComponentdecodeURIComponent 了,如果你不认识,可以上 MDN 学习。这里判定数据一定为正确的,实际使用中在 decode 这步中 JSON.parse 可能会报错,你需要自行处理一下,因为 url 可能会被人为修改。

const values = reactive({
  obj: { a: { b: { c: true } } },
});
const { syncToUrl } = useSyncUrl({
  configs: [
    {
      key: "obj",
      encode: (value) => encodeURIComponent(JSON.stringify(value)),
      decode: (value) => JSON.parse(decodeURIComponent(value)),
    },
  ],
});

详情页返回列表页

假如你的详情页有一个按钮点击返回列表页,要怎么保留上次的筛选条件呢?因为 vue-router 的 push 操作,不能直接传 url 参数的字符串,只能传对象,所以返回一个参数对象。

localStorage.setItem("listSearch", window.location.search);
// 在详情页
router.push(`/list${localStorage.getItem("listSearch")}`)
或
const { searchParams } = useSyncUrl(...)
localStorage.setItem("listSearch", JSON.stringify(searchParams))
// 在详情页
router.push({ path: "/list", query: JSON.parse(localStorage.getItem("listSearch")) })

结语

源码放在 github 了,readme 中还有测试地址,可以来试一试。

以上就是vue实现前端保持筛选条件到url并进行同步参数设计的详细内容,更多关于vue筛选条件url同步参数设计的资料请关注猪先飞其它相关文章!

原文出处:https://juejin.cn/post/7129783654657556493

[!--infotagslink--]

相关文章

  • vue中activated的用法

    这篇文章主要介绍了vue中activated的用法,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...2021-01-03
  • 基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件功能

    这篇文章主要介绍了基于vue-simple-uploader封装文件分片上传、秒传及断点续传的全局上传插件,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-02-23
  • Antd-vue Table组件添加Click事件,实现点击某行数据教程

    这篇文章主要介绍了Antd-vue Table组件添加Click事件,实现点击某行数据教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-11-17
  • vue 实现动态路由的方法

    这篇文章主要介绍了vue 实现动态路由的方法,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-06
  • Vue组件跨层级获取组件操作

    这篇文章主要介绍了Vue组件跨层级获取组件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-28
  • Vue基于localStorage存储信息代码实例

    这篇文章主要介绍了Vue基于localStorage存储信息代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-11-16
  • vue 监听 Treeselect 选择项的改变操作

    这篇文章主要介绍了vue 监听 Treeselect 选择项的改变操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
  • antdesign-vue结合sortablejs实现两个table相互拖拽排序功能

    这篇文章主要介绍了antdesign-vue结合sortablejs实现两个table相互拖拽排序功能,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-09
  • vue 获取到数据但却渲染不到页面上的解决方法

    这篇文章主要介绍了vue 获取到数据但却渲染不到页面上的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-19
  • vuejs element table 表格添加行,修改,单独删除行,批量删除行操作

    这篇文章主要介绍了vuejs element table 表格添加行,修改,单独删除行,批量删除行操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-18
  • vue项目多环境配置(.env)的实现

    最常见的多环境配置,就是开发环境配置,和生产环境配置,本文主要介绍了vue项目多环境配置的实现,感兴趣的可以了解一下...2021-07-20
  • vue项目页面嵌入代码块vue-prism-editor的实现

    这篇文章主要介绍了vue项目页面嵌入代码块vue-prism-editor的实现,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-10-30
  • Vue 3.0中jsx语法的使用

    这篇文章主要介绍了Vue 3.0 中 jsx 语法使用,帮助大家更好的理解和使用vue框架,感兴趣的朋友可以了解下...2020-11-13
  • 解决vue的router组件component在import时不能使用变量问题

    这篇文章主要介绍了解决vue的router组件component在import时不能使用变量问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-07-27
  • vue treeselect获取当前选中项的label实例

    这篇文章主要介绍了vue treeselect获取当前选中项的label实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
  • vue Treeselect下拉树只能选择第N级元素实现代码

    这篇文章主要介绍了vue Treeselect下拉树只能选择第N级元素实现代码,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-09-01
  • Vue中slot-scope的深入理解(适合初学者)

    这篇文章主要给大家介绍了关于Vue中slot-scope的深入理解,这个教程非常适合初学者,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-17
  • vue实现同时设置多个倒计时

    这篇文章主要为大家详细介绍了vue实现同时设置多个倒计时,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-05-20
  • Ant design vue table 单击行选中 勾选checkbox教程

    这篇文章主要介绍了Ant design vue table 单击行选中 勾选checkbox教程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-10-25
  • vue实现div单选多选功能

    这篇文章主要为大家详细介绍了vue实现div单选多选功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-07-16