计算机系统应用教程网站

网站首页 > 技术文章 正文

Vue.js 2 编程学习中 Vuex 的一些参考内容

btikc 2024-09-22 01:14:40 技术文章 23 ℃ 0 评论

从计数器开始

让我们从一个简单的计数器,开始进入Vuex 的世界:

vuex 计数器

计数器应用的数据模型很简单:使用一个counter属性来表示计数器的 当前值就够了。

在Vue实例的created钩子 中,应用启动了一个定时器,用来周期性地 递增counter属性的值 —— 由于counter是响应式属性,它的变化因而 驱动了视图随之刷新。

可以说counter抽象地表达了计数器视图的本质特征,当counter的 值确定时,我们可以确定地推理出视图的表现。像counter这样可以决定 视图表现的数据,在Vuex中就被称为状态。

计数器应用相当简单,因此我们只需要定义一个状态就可以了。稍微复杂 一些的应用,则可能需要我们抽象出成百上千的状态,这时候就需要分类 管理了。

例如,对于一个电商应用,我们将其购物车相关的状态归入cart类:

vuex 购物车

你看到,应用的全部状态,构成了一棵层级分明的状态树。而Vuex的作用 ,就在于管理一个应用的状态树。

应用单一状态树

Vuex进行应用状态管理 的第一个手段,是要求应用建立并维护一个单一的、全 应用范围共享的状态树,而不是各个组件单独维护自己的状态(在组件中使用data配置项声明) —— 不过这不是绝对的,那些完全不需要在多个组件间 共享的状态,依然可以在组件内部声明。

出于学习的目的,同时为了避免引入复杂的演示代码,我们假设计数器的counter状态需要与其他组件共享,因此我们将其定义迁移到状态树中。

创建状态库

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

conststore =newVuex.Store(
{
 state:{ counter:0}
 }
)

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

需要指出的是,状态库的state属性 —— 状态树 —— 是一个响应式属性,因此 我们可以使用状态树上的这些状态来驱动视图的自动更新。

使用计算属性访问状态树

在建立了全应用单一状态树之后,接下来我们要考虑的就是在组件中怎么使用 树上的状态了 —— 我们已经决定不声明组件的私有状态。

最简单的方法是将树上的状态,映射为组件的计算属性。例如,下面的代码将 状态树上的counter状态,映射为组件的可读写计算属性:

constEzCounter = {
 template:'{ {counter} }', 
 computed:{ 
 counter:{
 get() {returnstore.state.counter },
 set(v){ store.state.counter = v } 
 }
 }
}

将状态库注入组件

另一种方法是将状态库挂接为Vue实例的一个属性上,这样我们就可以在模板中 直接访问状态树了(模板的上下文对象是所属的Vue实例)。

在创建Vue实例时,使用store配置项,就可以将状态库挂接为Vue实例 的属性$store,而且这个Vue实例的所有后代实例,也都有$store指向 同一个状态库,看起来就像是将状态库注入了组件树上的每一个实例。

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

const EzCounter = {
 template:'{{$store.state.counter}}'
}
new Vue({ 
 store:store, 
 template:'', 
 components:{EzCounter}
})

状态变更管理

Vuex进行状态管理 的第二个手段,是承担起管理状态变更(mutation)的 责任。

Vuex要求组件将状态树视为只读,组件不应该直接修改状态树上的状态, 而是通过提申请的方式,由状态库来实际执行状态变更的操作:

vuex 状态

对于计数器应用来讲,修改counter状态的需求有两个:递增和复位。 因此,我们需要首先在状态库中声明两个变更处理器(mutation handler)。

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

conststore =newVuex.Store({
 state:{counter:0},
 mutations:{
 INCREASE:state=>state.counter++ ,
 RESET:state=>state.counter =0
 }
})

Vuex推荐使用大写字母来命名变更处理器,因为这个名字也将作为 组件提交的变更请求的类型名 —— 从组件的角度看,还有比大写的名字 更能表达出这是一个请求而不是实际操作吗 —— 回忆一下Windows 的WM_系列消息的名字。

状态变更处理器(mutation handler)的参数是一个局部上下文 (local context)对象的state属性,我们需要利用这个参数来 更新状态树上指定的状态。局部上下文是Vuex为实现状态树的模块化管 理而构造的状态库局部镜像,我们将在《模块化管理》章节详细讲解 局部上下文(local context)对象。现在,就把它暂时理解为原始的 状态库好了。

提交变更请求

组件应当调用状态库的commit()方法来提交指定类型的状态变更请求。 例如,下面的代码向状态库提交了递增counter状态的申请:

store.commit('INCREASE')

状态变更的同步性

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

这意味着,在状态变更处理器里不能执行异步代码。这一要求直接导致了新的 环节的引入 —— 状态动作(action):

Vuex 状态管理

根据作者的说法(原文参见:About mutations usefulness), 引入状态动作(action)这一环节的唯一目的,就是为了保证状态变更(mutation) 的同步性:"Actions vs. mutations is all about separating asynchronicity from actual mutations"

状态动作(action)隔离了组件和状态库,组件现在应当分发执行状态库声明的动作, 然后由状态动作负责提交变更请求。

在创建状态库时,使用actions配置项声明状态动作。例如,下面的代码 声明了两个状态动作inc和reset,分别用来提交INCREASE和RESET变更 请求:

conststore =newVuex.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') }
})

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

分发执行状态动作

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

store.dispatch('inc')

备注:本文内容参考汇智网的《vuex2入门与提高》。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表