继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

vuex的详细解析(一)

莫沫达
关注TA
已关注
手记 5
粉丝 1
获赞 12

在进入vuex之前,先看一看一个简单的关于计数器的例子,通过这个例子大概过一遍vuex的基本功能:图片描述
在Vue实例的created钩子中,应用启动了一个定时器,用来周期性地 递增counter属性的值 —— 由于counter是响应式属性,它的变化因而 驱动了视图随之刷新。像counter这样可以决定 视图表现的数据,在Vuex中就被称为状态。
图片描述
计数器应用相当简单,因此我们只需要定义一个状态就可以了。稍微复杂 一些的应用,则可能需要我们抽象出成百上千的状态,这时候就需要分类 管理了。就还比上图,应用的全部状态,构成了一棵层级分明的状态树。而Vuex的作用 ,就在于管理一个应用的状态树

应用单一状态树

Vuex进行应用状态管理的第一个手段,是要求应用建立并维护一个单一的、全 应用范围共享的状态树,而不是各个组件单独维护自己的状态(在组件中使用 data配置项声明)

Vuex的Store类就是一个状态库 ,用于管理状态树,它的实例化配置项state 用来声明要创建的状态树。例如,下面的代码创建了一个包含状态counter的 状态库:

const store = new Vuex.Store({
  state:{ counter:0 }
})

利用状态库的state属性,就可以访问到其管理的状态树了。例如,通过 store.state.counter来访问counter状态。

将状态库注入组件,是将状态库挂接为Vue实例的一个属性上,这样我们就可以在模板中 直接访问状态树了

在创建Vue实例时,使用store配置项,就可以将状态库挂接为Vue实例 的属性$store

例如,下面的代码使用store配置项,将状态库store注入根组件,因此 我们可以在EzCounter组件中利用$store属性访问状态库:

const EzCounter = { 
  template:'<div class="counter">{{$store.state.counter}}</div>'
}
new Vue({
  store:store,
  template:'<ez-counter/>',
  components:{EzCounter}
})

状态变更管理

Vuex要求组件将状态树视为只读,组件不应该直接修改状态树上的状态, 而是通过提申请的方式,由状态库来实际执行状态变更的操作:
图片描述
对于计数器应用来讲,修改counter状态的需求有两个:递增和复位。 因此,我们需要首先在状态库中声明两个变更处理器(mutation handler)。

在创建状态库时,使用mutations配置项来声明变更处理器。例如,下面 的代码为状态库声明了两个变更处理器:INCREASE和RESET:

const store = new Vuex.Store({
  state:{counter:0},
  mutations:{
    INCREASE: state => state.counter++ ,
    RESET: state => state.counter = 0 
  }
})

在组件中的使用方法:

methods:{
    inc() { this.$store.commit('INCREASE') }
  },

状态变更的同步性

Vuex要求应用保证状态变更(mutation)的 同步性 —— 状态变更处理器执行完之时,状态更新一定要完成。

这意味着,在状态变更处理器里不能执行异步代码。这一要求直接导致了新的 环节的引入 —— 状态动作(action):
在创建状态库时,使用actions配置项声明状态动作。例如,下面的代码 声明了两个状态动作inc和reset,分别用来提交INCREASE和RESET变更 请求:

const store = new Vuex.Store({
  state:{counter:0},
  mutations:{
    INCREASE:state => state.counter++,
    RESET: state => state.counter = 0
  },
  actions:{
    inc: context => context.commit('INCREASE'),
    reset: context => context.commit('RESET')
  }
})

context参数是一个局部上下文对象, 我们已经知道它是Vuex为模块构造的状态库局部镜像,因此调用它的commit()方法, 就可以提交变更请求了。

调用状态库的dispatch()方法来分发执行指定名称的状态动作。例如, 下面的代码要求状态库执行inc动作:

this.$store.dispatch('inc')

为什么要保证状态变更的同步性

Vuex作为一个状态管理系统,其核心特性就在于保证每一个状态变更(mutation)的 可跟踪性,这就是为什么状态变更处理器(mutation handler)必须是同步的,同步性的状态变更的意义,就在于每一个变更执行完成后都可以对应到一 个新的状态

假如,状态变更(mutation)是异步的,会怎么样?

这会导致状态变更与应用状态的不一致,因而导致了应用状态的不可预测性。
我们在RESET变更处理器中加入了异步代码:

const store = new Vuex.Store({
  state:{ counter:0},
  mutations:{
    RESET: state => setTimeout(() => state.counter = 0, 3000)
  }
})

看到应用提交了一个RESET变更请求时,我们将预测应用的 状态counter被重置为0,
但现在的问题是当点击按钮的同时couter状态并没有马上变化,而是3秒钟后异步代码执行后才发生改变,这就导致不可预测

未完待续。。。。。

打开App,阅读手记
1人推荐
发表评论
随时随地看视频慕课网APP