资讯专栏INFORMATION COLUMN

vuex状态初始化中间件设计

fireflow / 979人阅读

摘要:在之前使用的过程中,对于状态初始化的设计思路,是将其放到一个全局服务中,这样每次进到不同页面,只需要调用同一个全局的动作,就能完成初始化。同时,具体的初始化状态值,则由每个模块自己控制。的中间件有个特点,首先它提供了与动作的切入口。

总算把最近尝试的东西实现出来了,写点文章沉淀一下。

前言

单页面应用在使用单向数据流的设计方案后,状态树的控制就变得至关重要。这里面对的问题在于一个最基础的点,同时也是最常用的一点 -- 初始状态的控制与恢复
每次切换到一个页面,如果是动态数据页面,总是会先加载一些默认数据,或者清空现有数据,换句话说,就是初始化一下。
在之前使用vue + vuex的过程中,对于状态初始化的设计思路,是将其放到一个全局服务中,这样每次进到不同页面,只需要调用同一个全局的动作,就能完成初始化。同时,具体的初始化状态值,则由每个模块自己控制。

问题

在查看了vuex源码后,发现对于vuex的module而言,只是将所有module放到了同一个vm对象中,然后watch了一下。笔者之前在申明module中state对象时,经常使用const关键字,用意是认为申明时的state值一直作为静态值存在着,代表可返回的初始状态。而看了源码后,被打脸打飞了。。。。
那么怎么才能有一个静态的初始状态,让我们在切换页面时能够恢复呢?当然,最好这个初始状态时能够根据情况,可更替的。换句话说,这个所谓初始状态,应该是一个可定义的用于恢复的静态状态。

解决方案

Talk is cheap, show me the code.

来来来,一言不合就上代码~
源码以及相关样例可以在我的github上找到,链接点此

import Vue from "vue"

function deepClone(obj) {
  if (Array.isArray(obj)) {
    return obj.map(deepClone)
  } else if (obj && typeof obj === "object") {
    var cloned = {}
    var keys = Object.keys(obj)
    for (var i = 0, l = keys.length; i < l; i++) {
      var key = keys[i]
      cloned[key] = deepClone(obj[key])
    }
    return cloned
  } else {
    return obj
  }
}

const commonMutations = {
  INIT_STATE(state, moduleName) {
    state[moduleName] = deepClone(state.cache[moduleName])
  },
  CACHE_STATE(state, moduleName, newState) {
    state.cache[moduleName] = deepClone(newState)
  },
}

const commonActions = {
  initComponent({ dispatch }, name) {
    dispatch("INIT_STATE", name)
  },
  changeCacheState(store, module, state = store._vm[module]) {
    store.dispatch("CACHE_STATE", module, state)
  }
}

export default {
  onInit(state, store) {
    // hot load common mutations
    store.hotUpdate({
      mutations: commonMutations
    })
    // cache init state
    store._setupModuleState(state, {
        cache: {
          state: deepClone(state)
        }
      })
      // mixin all actions to the root vm
    Vue.mixin({
      vuex: {
        actions: commonActions
      }
    })
  }
}
关键点解读 1. 深层克隆

这里deep copy用了vuex源码里util的一个方法,官方注释上写着说比JSON.parse(JSON.stringify(obj))要来的更快,于是我就参(fu)考(zhi)过来了~~
什么?为什么要深拷贝?因为我们要维护一个静态状态的前端临时仓库呀~就像是前端的临时数据库一样,所谓数据驱动嘛~
于是下一步就是我们怎么把这个临时的静态状态对象让全局能够共享。这里用的方法就是一起扔到store绑定的vm对象上去

2. 全局使用便捷性

为了能够让代码全局都享受到这个便捷性,笔者在这里利用了vuex的中间件。vuex的中间件有2个特点,首先它提供了init与mutate动作的切入口。其次是它与store有着紧密联系。也因此,可以满足我们便捷性需要用到的2个需求:

应用启动时注册

应用全局可调用,不需要另外引入

所以就将init需要用到的commonMutation通过hotupdate的方式,在module初始化的时候,将init模块注册到全局,同时在store中加上当前模块初始状态的深拷贝
此外,利用了vue本身的mixin机制,将commonActions注册到全局的vm对象上
这样做的结果是什么呢?
去看看demo吧~~
地址在此

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80027.html

相关文章

  • Vuex — The core of Vue application

    摘要:个人看来,一个状态管理的应用,无论是使用,还是,最困难的部分是在的设计。中,并没有移除,而是改为用于触发。也是一个对象,用于注册,每个都是一个用于返回一部分的。接受一个数组或对象,根据相应的值将对应的绑定到组件上。 系列文章: Vue 2.0 升(cai)级(keng)之旅 Vuex — The core of Vue application (本文) 从单页应用(SPA)到服务器...

    Aldous 评论0 收藏0
  • 实现一个稍微复杂的simplelist

    摘要:是一个专门为应用所设计的集中式状态管理架构。此时可以帮助我们实现状态的管理。每个任务都归属于一个清单,有唯一的清单。说到这,一个复杂的的基本结构和功能已经出现了。 使用过一些清单类的应用程序,像 WunderList, Google Keep等,用来记录一些计划和安排,也试着将自己的计划安排同笔记一起整理在 Evernote 中,但是无论哪种方式用起来总觉得少了点什么,如果两者的一些功...

    solocoder 评论0 收藏0
  • 使用 Vuex + Vue.js 构建单页应用

    摘要:鉴于该篇文章阅读量大,回复的同学也挺多的,特地抽空写了一篇下的使用方法,传送门使用构建单页应用新篇华丽的分割线原文地址前言在最近学习的时候,看到国外一篇讲述了如何使用和来构建一个简单笔记的单页应用的文章。 鉴于该篇文章阅读量大,回复的同学也挺多的,特地抽空写了一篇 vue2.0 下的 vuex 使用方法,传送门:使用 Vuex + Vue.js 构建单页应用【新篇】 ---------...

    tomorrowwu 评论0 收藏0
  • 使用 Vuex + Vue.js 构建单页应用

    摘要:鉴于该篇文章阅读量大,回复的同学也挺多的,特地抽空写了一篇下的使用方法,传送门使用构建单页应用新篇华丽的分割线原文地址前言在最近学习的时候,看到国外一篇讲述了如何使用和来构建一个简单笔记的单页应用的文章。 鉴于该篇文章阅读量大,回复的同学也挺多的,特地抽空写了一篇 vue2.0 下的 vuex 使用方法,传送门:使用 Vuex + Vue.js 构建单页应用【新篇】 ---------...

    cnsworder 评论0 收藏0
  • 使用 Vuex + Vue.js 构建单页应用

    摘要:鉴于该篇文章阅读量大,回复的同学也挺多的,特地抽空写了一篇下的使用方法,传送门使用构建单页应用新篇华丽的分割线原文地址前言在最近学习的时候,看到国外一篇讲述了如何使用和来构建一个简单笔记的单页应用的文章。 鉴于该篇文章阅读量大,回复的同学也挺多的,特地抽空写了一篇 vue2.0 下的 vuex 使用方法,传送门:使用 Vuex + Vue.js 构建单页应用【新篇】 ---------...

    levius 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<