初识vuex
1.简介
vuex是 vue官方推荐的一个状态管理器。当我们遇到很多状态改变时,组件之间的通信就会变得复杂,这时候vuex的强大就展现出来。
我们从vuex的原理以及vuex的api两个部分介绍vuex
原理:
vuex的核心是store对象,它承载了vue的状态管理。vuex的实现分为了2个部分,第一个部分是store的创建,以及第二部分store的挂载,并且解析store。
vuex通过插件安装的形式来使得vue挂载vuex的store,当然这个是在vue组件的createBefore阶段实现的。随后Vuex将它直接挂载到 $options.$store 以供使用vue使用。
对于vuex的属性,Vuex 会将 vuex 属性解构成 getters 和 actions。并将 getters 的每个属性都挂载 vm 下(有可能被组件的 $options.data() 的属性覆盖),同时定义每个值的 getter 方法,但并不会定义 setter 方法,这是因为根据 Vuex 的设计是不允许开发者直接在组件内更改 store.state,而对数据的改动要通过提交 mutation。Vuex 实际上将 vm.vuex.getter 内的属性当作当前 vm 的计算属性来处理。和计算属性的区别是计算属性依赖计算的是 vm.$options.data 内的值,而 vm.vuex.getter 的属性依赖计算的是 store._vm.$options.data。这样所有组件的渲染都将都可以直接从状态树拿数据来渲染 UI 。
所有的组件都可以和vuex的状态树进行数据交互。但是不允许直接改变状态树的状态,应该用vuex的mutations来提交状态的改变。vuex会将actions内的方法绑定到vue的$options.methods下,它们与vue中定义的方法并没有区别。而 actions 内的方法将通过 dispatch 触发 mutations 来更新全局状态,actions方法与mutations的区别是,mutations改变state并且必须是同步改变,而actions可以作为异步提交的方法,dispatch 可以接收一个promise,并且返回一个promise。
2.API:
state:在vue中引入store对象,在子组件中通过this.$store来访问vuex中状态,并且我们最好在vue的computed中获取vuex的状态。
mapState:这是一个语法糖,可以快捷的获取更多的state。
接受一个object参数:
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex' export default {
// ...
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count, // 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count', // 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
当计算属性的名称和节点名称相同时,也可以接受一个数组对象。
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
对象展开:合成最终的computed属性
computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
getter:store的计算属性,在获取数据的时候,我们可以通过getter进行数据的操作,在相同地方用到的数据操作就不需要写一个公用的处理函数。它接受2个参数,state和getters。
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
mapGetters:
export default {
// ...
computed: {
// 使用对象展开运算符将 getters 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
}
}
或者
mapGetters({
// 映射 this.doneCount 为 store.getters.doneTodosCount
doneCount: 'doneTodosCount'
})
mutations:vuex提交状态的唯一方式。mutations更像一个事件监听器,当vue中commit了信息之后,相应的mutation才会执行相应的回掉函数。它接受2个参数,state和object。
因为vue是响应式的,所以mutations也应该遵守vue的动态绑定,所以在需要使用mutations前,尽量初始化。或者是添加时使用vue.set(obj,'new obj', 'value')或者以新运算符state.obj = { ...state.obj, newProp: 123 }
mutations必须是同步函数
组件中提交mutations:
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment' // 映射 this.increment() 为 this.$store.commit('increment')
]),
...mapMutations({
add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
})
}
}
actions: actions提交的是mutations,因为mutations是必须为同步状态,actions就提供了一种异步的形式提交mutations,我们可以在active中去做异步处理,并且提交mutation。它接受一个context参数,这个参数具有store对象相同属性和方法,但是并不是store本身。
actions: {
increment (context) {
context.commit('increment')
}
}
//或者 使用解值
actions: {
increment ({ commit }) {
commit('increment')
}
}
actions以dispatch来分发
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
}) // 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
组合的actions:
store.dispatch 可以处理被触发的action的回调函数返回的Promise,并且store.dispatch仍旧返回Promise
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
// 可以这样触发
//一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。
store.dispatch('actionA').then(() => {
// ...
}) // 也可以这样子触发
actions: {
// ...
actionB ({ dispatch, commit }) {
return dispatch('actionA').then(() => {
commit('someOtherMutation')
})
}
}
modules:
Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割。
const moduleA = {
state: { ... },
mutations: { ... },
actions: { ... },
getters: { ... }
}
const moduleB = {
state: { ... },
mutations: { ... },
actions: { ... }
}
const store = new Vuex.Store({
modules: {
a: moduleA,
b: moduleB
}
})
store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态
模块的局部状态
对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态。
const moduleA = {
state: { count: 0 },
mutations: {
increment (state) {
// state 模块的局部状态
state.count++
}
},
getters: {
doubleCount (state) {
return state.count * 2
}
}
}
对于模块内部的 action,context.state 是局部状态,根节点的状态是 context.rootState。
const moduleA = {
// ...
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
对于模块内部的 getter,根节点状态会作为第三个参数。
const moduleA = {
// ...
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
}
}
命名空间:
模块内部的 action、mutation、和 getter 现在仍然注册在全局命名空间——这样保证了多个模块能够响应同一 mutation 或 action。你可以通过添加前缀或后缀的方式隔离各模块,以避免名称冲突。你也可能希望写出一个可复用的模块,其使用环境不可控。例如,我们想创建一个 todos 模块:
// types.js // 定义 getter、action、和 mutation 的名称为常量,以模块名 `todos` 为前缀
export const DONE_COUNT = 'todos/DONE_COUNT'
export const FETCH_ALL = 'todos/FETCH_ALL'
export const TOGGLE_DONE = 'todos/TOGGLE_DONE'
// modules/todos.js
import * as types from '../types' // 使用添加了前缀的名称定义 getter、action 和 mutation
const todosModule = {
state: { todos: [] }, getters: {
[types.DONE_COUNT] (state) {
// ...
}
}, actions: {
[types.FETCH_ALL] (context, payload) {
// ...
}
}, mutations: {
[types.TOGGLE_DONE] (state, payload) {
// ...
}
}
}
我们也可以运用es6的新方法,symbol做命名;
需要了解更多关于symbol的信息,请移步阮一峰老师的ES6
参考文献:
初识vuex的更多相关文章
- 初识vuex vuex 的基本用法
Vuex 是什么? 官方是这么说的:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. 一个完 ...
- vue(21)初识Vuex
Vuex是做什么的? 官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式. 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化. Vuex ...
- Vuex ~ 初识
状态:data中的属性需要共享给其他vue组件使用的部分(即data中需要共用的属性) 1.初识vuex直接来个小demo 下面操作都是基于vue-cli,如果不了解先学习下vue-cli 利用n ...
- vuex的学习和理解
初识Vuex: vuex是 vue官方推荐的一个状态管理器,也是vue专用的一个插件.当我们遇到很多状态改变时,组件之间的通信就会变得复杂,这时候vuex的强大就体现出来了. Vuex 应用的核心就是 ...
- Vue爬坑之vuex初识
在 Vue.js 的项目中,如果项目结构简单, 父子组件之间的数据传递可以使用 props 或者 $emit 等方式 http://www.cnblogs.com/wisewrong/p/62660 ...
- Vuex初识
vuex是vue中单向数据流的一个状态管理模式,它可以集中存储管理应用中所有组件的状态,并且有一套相应的规则可以去预测数据的变化.类似与此的还有react中的redux,dva等状态管理模式. 一般我 ...
- [20190620]日常学习记录(三)-初识promise及vuex
在学习promise之前重温了Ajax的原生js实现, 在原生js中发送一个http请求首先new XMLHttpRequest() 然后定义状态变更事件 浏览器监听请求的状态,触发不同状态下相应的代 ...
- 前端笔记之Vue(四)UI组件库&Vuex&虚拟服务器初识
一.日历组件 new Date()的月份是从0开始的. 下面表达式是:2018年6月1日 new Date(2018, 5, 1); 下面表达式是:2018年5月1日 new Date(2018, 4 ...
- Vuex原来可以这样上手
在Mvc模式大行其道的今天,后端通过各种Mvc框架实现视图与数据模型的隔离,而前端这方面也发展迅速.vue实现了Dom与viewModel双向绑定,使其视图的更新影响模型,模型的更新影响视图,你会不会 ...
随机推荐
- php面向对象(OOP)---- 验证码类
PHP常用自封装类--验证码类 验证码是众多网站登陆.注册等相关功能不可以或缺的功能,实现展示验证码的方式有很多,这篇文章作者以工作中比较常用的方法进行了封装. 逻辑准备 要实现一个完整的验证码,需要 ...
- SQL中如何使用EXISTS替代IN
原创作品,可以转载,但是请标注出处地址http://www.cnblogs.com/V1haoge/p/6385312.html 我们在程序中一般在做SQL优化的时候讲究使用EXISTS带替代IN的做 ...
- Android名片扫描识别系统SDK
Android名片扫描识别系统SDK 一.Android名片扫描识别系统应用背景 这些年,随着移动互联的发展,APP应用成爆发式的增长,在很多APP中都涉及到对名片信息的录入,如移动CRM.移动端OA ...
- Linux驱动技术(七) _内核定时器与延迟工作
内核定时器 软件上的定时器最终要依靠硬件时钟来实现,简单的说,内核会在时钟中断发生后检测各个注册到内核的定时器是否到期,如果到期,就回调相应的注册函数,将其作为中断底半部来执行.实际上,时钟中断处理程 ...
- 小米wifi局域网下播放硬盘影片使用方法
因为家里没开网,看视频都要缓存到手机上. 后来听说小米wifi可以做为一个局域网服务器来用,没忍住就买了一个. 但是下载app之后才发现被坑. 小米路由器需要登录帐号之后才可以使用,而且每次开启都要登 ...
- groovy hello world
安装方法见官方文档http://groovy.codehaus.org/Installing+Groovy 用新一个文件HelloWorld.groovy,以utf8的编码保存,内容为: printl ...
- 3D Touch开发全面教程之Peek and Pop - 预览和弹出
## 3D Touch开发全面教程之Peek and Pop - 预览和弹出 --- ### 了解3D Touch 在iPhone 6s和iPhone 6s Plus中Apple引入了3D Touch ...
- Python从入门到放弃之迭代器
迭代器是Python2.1中新加入的接口(PEP 234),说明如下: The iterator provides a 'get next value' operation that produces ...
- Laravel路由和控制器的绑定
路由和控制器的关系 路由文件地址在\app\Http\routes.php,我们来看两种不同的路由. Route::get('/', function () { return view('welcom ...
- JavaWeb之DBUtils
一.什么是DBUtils及作用 DBUtils是apache公司写的.DBUtils是java编程中的数据库操作实用工具,小巧简单实用. DBUtils封装了对JDBC的操作,简化了JDBC操作.可以 ...