【前端笔记】Vuex快速使用
栏目: JavaScript · 发布时间: 5年前
内容简介:本文对 Vuex 官方文档重新组织编排,希望正在学习 Vue 的同学们,在阅读后可快速使用 Vuex。开始使用 Vuex,把状态拿到应用外部管理,Vuex管这个管理状态的玩意叫所谓状态管理,无非就是
本文对 Vuex 官方文档重新组织编排,希望正在学习 Vue 的同学们,在阅读后可快速使用 Vuex。
开始使用 Vuex,把状态拿到应用外部管理,Vuex管这个管理状态的玩意叫 Store ,一个完全独立的应用,他只负责状态管理。尝试把 Vuex 应用和 Vue 应用划清界限,
- 一个 Vuex 应用,做状态管理,可以理解是 Model 层
- 一个 Vue 应用,仅负责数据展示,纯纯的 View 层
Vuex 应用
所谓状态管理,无非就是 定义状态,修改状态 。
定义 state
在 Vuex 里定义状态,我们需要 new 一个 Store 出来,每一个 Vuex 应用的核心就是 store(仓库)。
// store.js import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); const store = new Vuex.Store({ state: { count: 0 } }); export default store; 复制代码
以上代码创建了一个 store, store.state
里定义了状态。与在 Vue 里定义 data 没有任何区别,
下面修改状态。
直接修改
如果你想快点用上 Vuex,你可以在组件里直接修改 store 里的 state,(直接修改的意思就是,用点操作修改)
state.count = 2; 复制代码
虽然这样可以正常工作,但在 严格模式 下会报错, 更改 store 中的状态的唯一方法应该是提交 mutation 。
严格模式
开启严格模式,仅需在创建 store 的时候传入 strict: true
:
const store = new Vuex.Store({ strict: true }); 复制代码
在严格模式下,无论何时发生了状态变更且不是由 mutation 函数引起的,将会抛出错误。
mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。
在 Vuex.Store 的构造器选项中,有一个 mutation 选项,这个选项就像是事件注册:key 是一个字符串表示 mutation 的类型(type),value 是一个回调函数(handler),
这个回调函数就是我们实际进行状态更改的地方,它有两个入参,第一个参数是 state,就是 store 里的 state;第二个参数是 Payload,这是提交 mutation 时候额外传入的参数。
定义 mutation
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment(state) { state.count++; // 变更状态 } } }); 复制代码
提交 mutation
上面定义了 mutation,要唤醒一个 mutation handler,唯一的接口是 store.commit
,如果你熟悉事件监听,commit 就类似于 Vue 的 $emit
,jquery 的 trigger
。
可想而知,commit 方法传参必须至少有一个能区分 mutation 的唯一标识,这个标识就是 type
,
commit 参数是对象
当 commit 的参数是一个对象的时候,对象里必须要有 type 字段,除了 type 字段,你还可以添加额外任意字段为载荷(payload)。
// 对象风格的提交方式 store.commit({ type: "increment", amount: 10 }); 复制代码
type 做第一参数
把 type 和 payload 分开也是个不错的选择,可以把 type 单独拿出来当第一个参数,以 commit(type,[payload])
的形式提交,官方称此为 以载荷形式提交
。
store.commit("increment"); store.commit("increment", 10); store.commit("increment", { count: 2 }); 复制代码
在大多数情况下,payload 应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读。
到这里我们已经知道如何定义 mutation 和提交 mutation 了,commit 接口很简单,但在哪里使用呢?有两个地方用
store.commit
Action
状态管理不过就是定义 state 和修改 state,mutation 已经可以修改 state 了,为什么还需要 action?
同步和异步
在 Vuex 中,mutation 都是同步事务,在 mutation 中混合异步调用会导致你的程序很难调试。
例如,当你调用了两个包含异步回调的 mutation 来改变状态,你怎么知道什么时候回调和哪个先回调呢?这就是为什么我们要区分这两个概念。
Action 确实和 mutation 很类似,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
注册 action:
注册 action 就跟定义 mutation 一样,除了 handler 的入参不同。
Action 函数的入参是一个与 store 实例具有相同方法和属性的 context
对象。因此可以
context.commit context.state context.getters
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment(state) { state.count++; } }, actions: { increment(context) { context.commit("increment"); } } }); 复制代码
分发 Action
Action 通过 store.dispatch
方法触发:
// 以载荷形式分发 store.dispatch("incrementAsync", { amount: 10 }); // 以对象形式分发 store.dispatch({ type: "incrementAsync", amount: 10 }); 复制代码
组合 Action
store.dispatch
可以处理被触发的 action 的处理函数返回的 Promise,并且 store.dispatch
仍旧返回 Promise,因此,通过 async / await
,很方便控制流程
actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // 等待 actionA 完成 commit('gotOtherData', await getOtherData()) } } 复制代码
表单处理
表单的问题在于使用 v-model
时候, v-model
会试图直接修改 state,而 Vuex 在严格模式下是不允许直接修改 state 的。
很容易解决,只要我们把修改 state 的行为按 Vuex 的要求以 commit mutation 方式修改即可。
有两种方式。
用“Vuex 的思维”解决
抛弃 v-model
指令,自己去实现 v-model
双向绑定,非常简单,
-
input
标签的value
属性绑定对应从 store 中映射来的计算属性, - 监听 input 事件,用 commit mutation 的方式,修改 store 里的 state。
<input :value="message" @input="updateMessage" /> 复制代码
computed: { ...mapState({ message: state => state.obj.message }) }, methods: { updateMessage (e) { this.$store.commit('updateMessage', e.target.value) } } 复制代码
store 中的 mutation 函数:
mutations: { updateMessage (state, message) { state.obj.message = message } } 复制代码
用 Vue 计算属性解决
如果坚持使用 v-model
,可以在 Vue 里对 v-model
绑定的计算属性设置 set 行为。
<input v-model="message" /> 复制代码
computed: { message: { get () { return this.$store.state.obj.message }, set (value) { this.$store.commit('updateMessage', value) } } } 复制代码
使用 Vuex 进行状态管理,到此结束。
从 flux 架构来看,三个核心, State , Mutation , Action ,已经足够了,总结一下其实很简单, 同步 commit mutation,异步 dispatch action 。
核心原则
- 应用层级的状态应该集中到单个 store 对象中。
- 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
- 异步逻辑都应该封装到 action 里面。
记住这些原则,开始动手把 Vuex 集成到 Vue 项目中吧,至于一些更多的概念,都是些锦上添花的东西。
Vue 应用使用 Vuex
Vuex 的常用 api 上面都涉及到了,使用思路就是
-
定义状态:通过
new Vuex.Store({})
创建一个 store 实例,定义 state,getters,actions,mutations。 -
改变状态:使用
store.commit
提交mutation
,使用store.dispatch
分发actions
。
现在状态管理的部分已经全部由 store 实例去管理了,如何在 Vue 组件中使用 store,非常简单,一点也不神奇。
在 store.js
文件里我们创建了 store 实例并将其导出了(export),按照 js 模块化的知识,我们只要在需要的地方导入它就可以直接使用了。
组件引入 store
可以在需要的组件里直接引入,就像引入一个普通的 js 一样。
import store from "path/to/store.js"; 复制代码
组件中引入了 store,就可以直接通过 store.state
引用 state,以及直接使用 store 实例简洁的 api,真的就是这么简单。
store.state.count = 2; // 直接修改,并不建议 store.commit(); // 在 store 中调用 mutation store.dispatch("increment"); // 在 store 中分发 action 复制代码
我们往往需要在 Vue 组件的 template
中展示状态,由于 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在 计算属性
中返回某个状态:
import store from "path/to/store.js"; const Counter = { template: `<div>{{ count }}</div>`, computed: { count() { return store.state.count; } } }; 复制代码
每当 store.state.count
变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。
其实到现在为止,对于在 Vue 中使用 Vuex 就已经足够了。下面的东西其实可以不用看了,但 Vuex 还是提供了一些方便我们使用的方式,锦上添花。
组件中引入的方式,缺点:这种模式导致组件依赖全局状态单例。在模块化的构建系统中,在每个需要使用 state 的组件中需要频繁地导入。
全局引入 store
Vuex 通过 store 选项,提供了一种机制将状态从根组件“注入”到每一个子组件中:
// app.js import Vue from "vue"; import store from "path/to/store.js"; const app = new Vue({ store // 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件 }); 复制代码
通过在 根实例
中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store
访问到。这样我们就不用每个组件单独引入了。
this.$store.state.count = 2; // 直接修改,并不建议 this.$store.commit("", {}); // 直接在组件中提交 mutation this.$store.dispatch("increment"); // 在组件中分发 action 复制代码
组件绑定的辅助函数
- mapState
- mapGetters
- mapMutations
- mapActions
既然是辅助,就不是必须的东西,辅助函数可以方便的把 Vuex 中的 state,getter,mutation,action 映射到组件,方便调用。
更多概念
Getter
如果你很喜欢 Vue 提供的计算属性(computed),Vuex 允许在 store 中定义“getter”(可以认为是 store 的计算属性)。
但对状态管理来说,Getter 其实并不是必须的,如果你需要的话,可以查看文档使用。
Module
模块化并不是状态管理的概念,也不是必须的,但如果应用十分复杂,将 store 分割成模块(module)会是一个必经之路,Vuex 提供了模块化选项,需要可查看文档。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python深度学习
[美] 弗朗索瓦•肖莱 / 张亮 / 人民邮电出版社 / 2018-8 / 119.00元
本书由Keras之父、现任Google人工智能研究员的弗朗索瓦•肖莱(François Chollet)执笔,详尽介绍了用Python和Keras进行深度学习的探索实践,涉及计算机视觉、自然语言处理、生成式模型等应用。书中包含30多个代码示例,步骤讲解详细透彻。由于本书立足于人工智能的可达性和大众化,读者无须具备机器学习相关背景知识即可展开阅读。在学习完本书后,读者将具备搭建自己的深度学习环境、建......一起来看看 《Python深度学习》 这本书的介绍吧!