浅谈vuex 闲置状态重置方案


Posted in Javascript onJanuary 04, 2018

前言

大型单页应用(后面都是指spa),我们往往会通过使用状态管理器 vuex 去解决组件间状态共享与状态传递等问题。这种应用少则几十个单页,多则上百个单页。随着路由的频繁切换,每个路由对应的 vuex 中的状态将越来越多。为了做到页面的极致优化,我们需要将那些闲置的状态重置,以减小占用的内存空间。

什么状态可以重置

vuex 强调采用集中式存储管理应用的所有组件的状态,但是我们真把所有的状态都放到 store 中去处理,你会发现开发起来非常痛苦。这里如果想很好的把控哪些数据需要放到 store 中去管理,首先要理解 vuex 是用来解决什么问题的。vuex 官网指出是为了解决 多个组件共享状态 的,那么我们就可以把多个组件的共享状态放到 store 中去管理,这里的多组件共享对于单页应用很多情况是跨路由的组件。如果 store只存储多组件共享的状态,那么我们就没必要去清理 vuex 中的状态了,因为这些状态随时会被用到。

而随着业务场景越来越复杂,很多与后台交互的逻辑也都放到了组件中,这样代码就变得很凌乱,vuex 也没有被充分利用。这时我们可以把与后台 api 交互的逻辑放到 vuex 中的action 去处理,后台返回的状态自然也就放到了 store 管理。这样处理后,组件就只负责对数据进行渲染,逻辑非常清晰。而此时,组件对应的 store 中的状态随着路由的切换将会越来越多,而这些状态就需要我们手动的去清理了。

很多方案都有取舍,如果将与后台 api 交互的数据放到组件中,就没必要去清理了,但是代码逻辑将变得比较乱。另外诸如 vuex 的插件vue-devtools 将无法监控到每次请求数据的变化...

什么时候去重置状态

我们想要的效果是在路由切换的时候,把上一个路由对应的 vuex 中的状态重置掉,但是路由和vuex 并没有一一对应的关系,如果要做到这种效果,那么我们需要维护一个路由与vuex 模块的对应关系,这样会很繁琐。不如当路由改变时去重置 vuex 中的所有状态。

vuex 中闲置状态如何清理

下面将结合我的github实例 去说明,这个实例创建了一个单页应用,我们通过切换路由的时候将闲置的状态清除。

改造路由对应组件的 module 状态

实例中采用拆分 store 为多个 module 的方式,将路由对应的组件状态放到对应的 module 中,多组件共享的状态放到顶级的 store 中管理。大致如下:

// store/index.js
import page1 from "./modules/page1.js";
import page2 from "./modules/page2.js";
import page3 from "./modules/page3.js";
import page4 from "./modules/page4.js";
import page5 from "./modules/page5.js";

export default new Vuex.Store({
  state,
  getters,
  actions,
  mutations,
  modules: { // 每个路由对应的 module
    page1,
    page2,
    page3,
    page4,
    page5
  },
  plugins: __DEV__ ? [createLogger()] : [],
  strict: __DEV__ ? true : false
});

路由 page1 对应的 module 的 state 形如:

// store/modules/page1.js
const state = {
   // 列表数据
   page1Data: [],
   // 标题数据
   page1Title: ''
}

这些数据是通过调用后端 api 返回并复制的数据,如果我们在路由改变的时候重置这些数据,那么需要将初始化数据提取出来,并且暴露一个需要重置的标识方法 initState() ,代表路由改变的时候需要重置,当然这个方法名称是个约定,你也可以定义为其他名称。改造后为:

// store/modules/page1.js
// 放置你要重置的数据
const initState = {
  page1Data: [],
}

// state
const state = {
  // 参数解构
  ...initState,

  // 路由改变不想重置的数据
  page1Title: '',
  initState(){
    return initState
  }
}

全局 module 配置

定义全局 mutation 事件类型

// store/types.js
export const RESET_STATES = 'resetStates'

定义全局 mutation

// store/mutation.js

import * as types from './types'

// 检测所有的 state 并把 `initState()` 中的属性重置
function resetState(state, moduleState) {

  const mState = state[moduleState];

  if (mState.initState && typeof mState.initState === 'function') {

    const initState = mState.initState();

    for (const key in initState) {

      mState[key] = initState[key];
    }
  }

}

export default {

  [types.RESET_STATES](state, payload) {

    for (const moduleState in state) {

      resetState(state, moduleState);
    }
  },

}

定义全局 action

// store/action.js
import * as types from './types'

export default {
  // rest state action
  resetStates:function (context, payLoad) {

    context.commit(types.RESET_STATES, payLoad);
  }
}

路由切换触发重置方法

至此一切准备就绪,只需要在路由改变时触发重置的方法即可,在入口 vue 文件中处理

// components/app.vue
<script>
  import {mapState, mapActions} from "vuex"
  export default{

    methods: {

      ...mapActions({
        resetStates: "resetStates"
      })
    },

    watch: {

      $route(to, from) {
        // 路由改变发起重置
        this.resetStates();
      }
    }
  }
</script>

如果你的 chrome 浏览器安装了vuejs-devtools 在路由切换的时候就能够很清晰的看到上一个路由数据的的重置过程。

总结

实例点这里 。我们这里的 vuex 状态重置,是每次路由切换遍历所有的 store 中的状态,并把 initState() 中的属性重置,如果能做到把当前的路由对应的 state 重置就更好了,但是路由和 store 中的 module 并没有关联关系。这里只是提供一种重置 vuex 状态的一种方案,如果有更好方案还请各位看官留言。如有不妥的地方也欢迎拍砖留言。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
经典的带阴影的可拖动的浮动层
Jun 26 Javascript
javascript中对对层的控制
Dec 29 Javascript
jQuery 处理网页内容的实现代码
Feb 15 Javascript
一款由jquery实现的整屏切换特效
Sep 15 Javascript
论JavaScript模块化编程
Mar 07 Javascript
Linux下为Node.js程序配置MySQL或Oracle数据库的方法
Mar 19 Javascript
javascript的replace方法结合正则使用实例总结
Jun 16 Javascript
jQuery插入节点和移动节点用法示例(insertAfter、insertBefore方法)
Sep 08 Javascript
JS前端加密算法示例
Dec 22 Javascript
详解Node.js access_token的获取、存储及更新
Jun 20 Javascript
vue-router命名路由和编程式路由传参讲解
Jan 19 Javascript
vue实现抖音时间转盘
Sep 08 Javascript
详解Angular5 服务端渲染实战
Jan 04 #Javascript
JavaScript中的高级函数
Jan 04 #Javascript
Three.js 再探 - 写一个微信跳一跳极简版游戏
Jan 04 #Javascript
JS实现带导航城市列表以及输入搜索功能
Jan 04 #Javascript
微信小程序实现的贪吃蛇游戏【附源码下载】
Jan 03 #Javascript
详解Angular2学习笔记之Html属性绑定
Jan 03 #Javascript
Angular2学习笔记之数据绑定的示例代码
Jan 03 #Javascript
You might like
比特率,大家看看这个就不用收音机音质去比MP3音质了
2021/03/01 无线电
老机欣赏|中国60年代精品收音机
2021/03/02 无线电
Syphon 虹吸式咖啡壶冲煮–拨动法
2021/03/03 冲泡冲煮
frename PHP 灵活文件命名函数 frename
2009/09/09 PHP
10个可以简化php开发过程的MySQL工具
2010/04/11 PHP
Yii2.0多文件上传实例说明
2017/07/24 PHP
php设计模式之策略模式实例分析【星际争霸游戏案例】
2020/03/26 PHP
jQuery 获取URL参数的插件
2010/03/04 Javascript
jQuery学习笔记(1)--用jQuery实现异步通信(用json传值)具体思路
2013/04/08 Javascript
可兼容IE的获取及设置cookie的jquery.cookie函数方法
2013/09/02 Javascript
纯JS实现根据CSS的class选择DOM
2014/03/22 Javascript
如何获取网站icon有哪些可行的方法
2014/06/05 Javascript
JavaScript中apply方法的应用技巧小结
2016/09/29 Javascript
JS常用倒计时代码实例总结
2017/02/07 Javascript
关于javascript sort()排序你可能忽略的一点理解
2017/07/18 Javascript
vue router 配置路由的方法
2018/07/26 Javascript
微信小程序中使用自定义图标(阿里icon)的方法
2018/08/20 Javascript
[02:35]DOTA2英雄基础教程 狙击手
2014/01/14 DOTA
[04:21]狐狸妈带你到现场 DOTA2 TI中国区预选赛线下赛路线指引
2014/05/22 DOTA
使用Python脚本实现批量网站存活检测遇到问题及解决方法
2016/10/11 Python
PyQt5+python3+pycharm开发环境配置教程
2020/03/24 Python
keras实现VGG16 CIFAR10数据集方式
2020/07/07 Python
Farnell德国:电子元器件供应商
2018/07/10 全球购物
俄罗斯最大的灯具网站:Fandeco
2020/03/14 全球购物
abstract是什么意思
2012/02/12 面试题
简述Linux文件系统通过i节点把文件的逻辑结构和物理结构转换的工作过程
2016/01/06 面试题
班组长工作职责
2013/12/25 职场文书
四下基层实施方案
2014/03/28 职场文书
电子信息专业应届生自荐信
2014/06/04 职场文书
法学专业求职信
2014/07/15 职场文书
入党积极分子批评与自我批评思想汇报
2014/09/14 职场文书
三潭印月的导游词
2015/02/12 职场文书
关于召开会议的通知
2015/04/15 职场文书
地心历险记观后感
2015/06/15 职场文书
Java9新特性之Module模块化编程示例演绎
2022/03/16 Java/Android
Win11怎么修改电源模式?Win11修改电源模式的方法
2022/04/05 数码科技