如果非要去解释应用程序‘状态’这个词,那我就自以为是的总结——应用程序状态就是应用程序现在的样子,应用程序的状态与时间强相关,理论上应用程序任何时刻的状态都不相同。
jquery 时代
前端状态管理这个概念出现的时间还不长,但是在状态管理概念出现之前前端就已经有状态管理相关的实践了,我从 2017 年开始使用 jquery,在 jquery 时代,我们经常取 DOM 节点的某个属性值,然后根据这个属性值判断接下来的操作。很多地方都能取属性值,很多地方都能修改属性值。那个时候的状态存储是分散的,我们对相互依赖的状态很难进行处理,或者说处理起来很麻烦。在这个时候要如何去规范状态管理,如何组织项目结构也没有规范可以遵循。
总的来说,在 jquery 时候没有状态管理的概念,状态存储是分散的,状态的访问与修改没有限制
前端社区现代状态管理
Vuex
Vuex
是一个专为Vue.js
应用程序开发的状态管理模式。可以管理复杂应用的数据状态,比如兄弟组件的通信、多层嵌套的组件的传值等等。
通俗的来说vuex就是全局数据管理,用来管理全局数据的,vue原本的数据管理只能父子组件之间传递数据,并且不方便,使用vuex可以进行全局数据管理,将所有数据存储到vuex中,使用时调用
vuex的核心:
state 定义了应用状态的数据结构,可以在这里设置默认的初始状态。
mutations 是唯一更改 store 中状态的方法,且必须是同步函数。
actions 用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
getter 允许组件从 Store 中获取数据,mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性。
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)const store = new Vuex.Store({ state: { //存放初始数据 count: 0 }, mutations: { //存放修改数据的方法 increment (state) { state.count++ } }})
1.State
假设我们有一个全局状态count的值为5。那么,我们就可以将其定义为 state 对象中的key和value,作为全局状态供我们使用。如下:
//创建一个 store
const store = new Vuex.Store({ //state存储应用层的状态 state:{ count:5 //总数:5 } });
2.Getters
可以认为,
getters
是store的计算属性,类似于computed,对state里的数据进行一些过滤,改造等等
假设我们要在state.count
的基础上派生出一个新的状态newCount出来,就适合使用我们的 getters
getters 接受 state 作为其第一个参数
const store = new Vuex.Store({ //state存储应用层的状态 state:{ count:5 //总数:5 }, getters:{ newCount:state => state.count * 3 } });
在组件中获取{{newCount}}方式:
export default { computed: { newCount(){ return this.$store.getters.newCount; } }};
3.Mutations
Vuex给我们提供修改仓库 store中的状态的唯一办法就是通过提交mutation ,且必须是同步函数
我们在 mutations中定义了一个叫increment的函数,函数体就是我们要进行更改的地方
会接受 state作为第一个参数,第二个是自定义传参
const store = new Vuex.Store({ //state存储应用层的状态 state:{ count:5 //总数:5 }, mutations:{ increment(state,value){ state.count += value; } } });
我们在提交commit时候,字符串参数increment,就是对应在 mutations中的increment。一般通过方法或钩子触发,例如:
methods: { getVal(event) { //获取当前的按键的值 let value = event.target.dataset.value; //通过commit提交一个名为increment的mutation this.$store.commit("increment", value); } }
在组件中获取{{count}}方式:
export default { computed: { count(){ return this.$store.state.count; } }};
4.Action
用于提交 mutation,而不是直接变更状态,可以包含任意异步操作。
只有通过action=>mutations=>states,这个流程进行操作,具体步骤如下:
export default new Vuex.Store({ //存放数据 state: { obj: {}, }, //4.通过commit mutations中的方法来处理 mutations: { getParam (state,Object) { //5.修改state中的数据 state.obj= Object } },
//2.接受dispatch传递过来的方法和参数
actions: { getParamSync (context,Object) { //处理异步操作 setTimeout(()=>{ //3.通过commit提交一个名为getParam的mutation //action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation context.commit('getParam',Object) },3000) } }})
然后我们就在组件里这么调用就可以了
methods: { getVal() { let name= 'xia'; let age= '26'; let sex= 'man'; //1.通过dispatch将方法getParamSync和多个参数{name,age,sex}传递给actions this.$store.dispatch('getParamSync',{name,age,sex}) } }
Vuex 是 Vue 的一个插件,可以说它是专门为 Vue 应用程序做状态管理而生的。与 redux 一样,Vuex 它集中存储管理应用的状态,要改变 store 中的 state 只能通过 commit mutation,从这点来看 Vuex 也遵循 Flux 思想。由于 Vue 在渲染的时候会自动收集并追踪依赖,所以 Vuex 的状态是响应式的。如果 Vue 组件从 store 中读取状态,当 store 中的状态发生变化时,相应的组件也会得到更新。
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // mutate state state.count++ } }, actions: { incrementAsync ({ commit }) { setTimeout(() => { commit('increment') }, 1000) } }})store.commit('increment')store.dispatch('incrementAsync')
数据流图如下:
在 Redux 和 MobX 中的 action 是一个虚拟的概念,Vuex 中的 action 是 store 中的一部分,它是专门用来做异步操作的,它可以返回一个 promise。
总结
使用Vuex 做状态管理,状态的变化能够被感知和响应,当配合视图层框架或库使用时,状态的变化能够驱动界面的变化,这些只是当代状态管理库的基本功能。在实际项目中我们还应该关注代码的组织结构,特别是在一些重业务逻辑轻视图的项目中规范化、结构化业务逻辑尤为重要,在开发范式上面让复杂系统有结构,让不同经验的开发人员写出来的代码相差不大,从而让业务逻辑结构简单化。Vuex 或多或少在代码的组织结构上有一些要求,但是在让业务逻辑结构化上关注的还比较少。