Vue2中缓存列表页搜索参数

时间:2021-2-20 作者:admin

本次需求描述:

当前列表页可进行条件搜索,有一些操作例如:查看详情,编辑等需要跳转路由。现在是想要在返回列表页时保留之前的搜索项等
需要解决的问题:
1.详情页面,或者编辑页但是不进行编辑直接返回
2.编辑操作成功之后进行返回。

解决思路:

– 第一种场景:没有对数据进行任何操作,可以看做是只进行了查看,这类问题可以用keep alive解决
– 第二种场景:对数据进行了操作,所以返回列表页的时候必须保证列表页数据时最新的状态。比如当前数据是暂存状态,是可以对数据进行修改的,也就是列表页有个修改按钮,这个按钮是只有暂存状态才应该展示。当前数据修改提交完成后,应该是没有修改按钮的,如果用keep alive的话数据还是旧的数据和状态,这样会导致依然存在修改按钮,所以这种场景中需要刷新表格,也就是需要把搜索项和分页等列表页的参数进行保存。
这两种场景下文为了方便可能统一称呼为缓存起来。

具体的解决步骤和遇到的问题

在实现之前需要明白,虽然是两种方式。但是实际中第一种场景可单独存在(只是详情页面,没有对数据进行修改的操作),第二种场景必定与第一种共存(因为你的比如修改页码,可以进行修改,但是也可以不修改直接返回)
如下的所有代码基本都是伪代码,可借鉴思路,具体实现还是要根据自己的实际情况进行修改。(因为我有部分实现就是和自己的逻辑组件之类的耦合在了一起,然后又懒得分离开来,就删删减减复制了过来)

keep alive

通过keep alive的include设置都有哪些页面需要进行缓存,这个keepAliveList数组(需要被缓存页面name所组成的)保存在vuex中
核心代码
store/modules/keepAlive.js

const state = {  
  keepAliveList: []
}
const mutations = {  
  SET_KEEP_ALIVE_LIST: (state, pageName) => {    
    if (!state.keepAliveList.includes(pageName)) {      
      state.keepAliveList = [...state.keepAliveList, pageName]    
    }  
},
  DEL_KEEP_ALIVE_LIST: (state, pageName) => {
    if (state.keepAliveList.includes(pageName)) {
      const index = state.keepAliveList.findIndex(item => item === pageName)
      state.keepAliveList.splice(index, 1)
    }
  }
}

keep alive遇到的问题:

最开始的基本思路是:

在list页面做判断,如果去往的页面是detail页面,那么缓存list页面,否则删除。

// list页面
beforeRouteLeave(to, from, next) {
  if(to.path === '详情') {
    this.$store.commit('keepAlive/SET_KEEP_ALIVE_LIST', this.$option.name)
  } else {
    this.$store.commit('keepAlive/DEL_KEEP_ALIVE_LIST', this.$option.name)
  }
  next()
}

这种实现方式出现的问题:

第一次从list页面跳转详情,从详情返回可以正常缓存。如果是第二次从list页面跳转详情,从详情返回list页面会发现既触发created,又触发了activated

后来发现其实是思路错了,改为在进入list页面的时候进行缓存,如果跳转的不是detail页面,那么删除当前页面的缓存

beforeRouteEnter(to, from, next) {
  next(vm => {
    vm.$store.commit('keepAlive/SET_KEEP_ALIVE_LIST', vm.$options.name)
  })
},
beforeRouteLeave(to, from, next) {
  if (to.path !== '详情') {
    this.$store.commit('keepAlive/DEL_KEEP_ALIVE_LIST', this.$options.name)
  }
  next()
}

保留搜索条件:

点击查询的时候把当前页面的搜索参数和页码存在vuex中,然后在当前list页面判断vuex中是否有搜索项,如果有的话会搜索这些条件。
这里面有个点就是:vuex中有数据,但是不是所有时候都需要搜索这些条件。只有是从当前list页面跳转出去,然后返回list页面才需要搜索条件

// vuex:
SET_PAGE_PARAMS: (state, obj) => {
  Object.keys(obj).forEach(k => {
    state.pageParams = {
      [k]: {
        ...state.pageParams[k],
        ...obj[k]
      }
    }
  })
},
DEL_PAGE_PARAMS: (state, name) => {
  if (!name) return
  delete state.pageParams[name]
}
// 搜索区域所在页面或组件代码
// (pageParams是除了page和size之外的搜索条件,因为我的搜索和表格分属两个组件,所以保留参数这部分也分开了)
this.$store.commit('keepAlive/SET_PAGE_PARAMS', {搜索条件})
// 表格区域所在页面或组件代码
created() {
  const parentName = this.$parent.$options.name
  if (Object.keys(this.pageParams).includes(parentName)) {
      const { searchCondition = {}} = this.pageParams[parentName]
      Object.keys(searchCondition).forEach((item) => {
      tableSearchParams[item] = searchCondition[item]
    })
  }
  if (this.pageParams[parentName]) {
    this.currentPage = this.pageParams[parentName].page || 1
    this.currentSize = this.pageParams[parentName].size || 10
  }
  this.getList({ initialParams: tableSearchParams })}
// 同样是表格所在页面或组件代码,要在getList方法里面判断,如果当前list页面的name在keepAliveList中的话,也就意味着这个页面需要被缓存
getList({ initialParams = {} } = {}) {
  const pageParams = {
    page: this.currentPage,
    size: this.currentSize
  }
  const parentName = this.$parent.$options.name
  if (this.keepAliveList.includes(parentName)) {
    const tempObj = {
      [this.$parent.$options.name]: pageParams
    }
    this.$store.commit('keepAlive/SET_PAGE_PARAMS', tempObj)
  }
...
}
// list页面代码
// list页面原有的跳转路由代码中额外增加,这个needKeepAlive变量是否需要被缓存或者说是否需要保留搜索参数。
this.$store.commit('keepAlive/SET_NEED_KEEP_ALIVE', true)

// ---分割线---
created() {
  this.$store.commit('keepAlive/SET_NEED_KEEP_ALIVE', false)
},
activated() {
  this.$store.commit('keepAlive/SET_NEED_KEEP_ALIVE', false)
},
beforeRouteLeave(to, from, next) {
  // 这个routeList是list页面所有跳转出去的路由组成的数组。
  if (!this.routeList.includes(to.path) || !this.needKeepAlive) {
    this.$store.commit('keepAlive/DEL_KEEP_ALIVE_LIST', this.$options.name)
    this.$store.commit('keepAlive/DEL_PAGE_PARAMS', this.$options.name)
  }
// 从list页面调到详情或者编辑页面之后,只有返回当前list页面才有是否需要缓存这种考虑,如果不是返回当前list页面就把当前页面的搜索参数和keepAliveList对应清空就行
  if (this.needKeepAlive) {
    to.meta.isKeepAlive = true
    to.meta.fromPath = this.$route.path
    to.meta.fromName = this.$options.name
  }
  next()
}
// 详情或者编辑页面:
beforeRouteLeave(to, from, next) {
  const { isKeepAlive = false, fromPath = '', fromName = '' } = this.$route.meta
  if (to.path !== fromPath || !isKeepAlive || !this.keepAliveMode) {
    this.$store.commit('keepAlive/DEL_PAGE_PARAMS', fromName)
    this.$store.commit('keepAlive/DEL_KEEP_ALIVE_LIST', fromName)
    return next()
  }
  if (this.keepAliveMode === 'update') {
    this.$store.commit('keepAlive/DEL_KEEP_ALIVE_LIST', fromName)
    return next()
  }
  next()
}

// 同时在操作成功返回中增加
this.keepAliveMode = 'update'

// 在单纯返回上一页面中增加
this.keepAliveMode = 'detail'

保留数据到这里就成功了。还有个东西要处理,就是search组件,如果有初始条件的话,需要展示这些默认值。(默认值展示部分就不做过多展开了。一般情况就是v-model的值变成你保存的数据即可)
search中一般而言了包含级联下拉这种情况,也就是选择了前一项下拉,根据值调用下一个下拉的接口。(这部分记得特殊处理,因为我这部分和我本身的search组件有点耦合太高,所以也没有复制过来。。。)

搜索条件默认展示时小问题

一般是先调用完下拉选项的接口,再赋默认值。我是相当于把所有的下拉选项接口保存在一个数组中,然后循环调用。
但是用forEach循环的话不能保证接口结束完再执行赋默认值,需要用for of,这部分执行顺序问题可以参考

阮一峰老师的es6入门教程

es6.ruanyifeng.com/#docs/async

for (const item of cascadeArr) {
  const val = searchCondition[item.prop]
  await this.selChange(xxx)
}
// 这里再赋默认值

END

如果有看到这里的大佬有好的实现方法希望不吝赐教

这里是真的end了~~

声明:本文内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎进行举报,并提供相关证据,工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。