vuex入门
安装&使用
npm install vuex --save
- 1
通过Vue.use()来使用:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
- 1
- 2
- 3
- 4
Vuex是什么
Vuex是一个专为vue.js应用程序开发的状态管理模式。它集中储存该应用的所有数据,统一保管。便于维护。
核心概念
state
vuex使用单一状态树,也就是一个对象包含了整个应用的所有状态,它作为唯一的数据源。也就是说,每个应用仅有一个store实例。
在Vue组件中获得Vuex状态
Vuex用过store选项,提供了一种机制,将数据从跟组件注入到每个子组件中(需要调用Vue.use(Vuex)):
import store from './store'
new Vue({
el: '#app',
// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
store,
template: '<App/>',
components: { App }
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
通过在根实例中注册store选项,该store实例会注入到根组件下的所有子组件中。且子组件能通过this.$store访问到:
const Counter = {
template: `<div>{{ count }}</div>`,
//从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态:
computed: {
count () {
return this.$store.state.count
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
mapState辅助函数
当一个组件需要获取多个状态时,逐个声明计算属性会很麻烦,为此我们可以使用mapState辅助函数帮我们生成:
// 在单独构建的版本中辅助函数为 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
}
})
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
上边我们给mapState传了一个对象,如果我们要生成的计算属性名称与state子节点名称相同时,也可以直接给mapState传入一个字符串数组:
computed: mapState([
// 映射 this.count 为 store.state.count
'count'
])
- 1
- 2
- 3
- 4
对象展开运算符
mapState函数返回的是一个对象,但是一个组件中的计算属性,不仅有来自store的,还有它局部的。那么如何混用呢?我们使用对象展开运算符:
computed: {
//localComputed 是组件的局部计算属性
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
组件仍保有局部状态
上边说了组件的局部状态,也就是只有这个组件自己需要用到的数据,比如模态框组件是否显示的状态,这个数据只对该组件本身有意义,所以不应该放入Vuex,作为局部状态,反而更利于维护。
Getters
有时候我们需要从store中的state中派生出一些状态,例如对列表进行过滤并计数:
computed: {
doneTodosCount () {
return this.$store.state.todos.filter(todo => todo.done).length
}
}
- 1
- 2
- 3
- 4
- 5
但如果我们要在多个组件中使用此属性,难道要复制这个函数吗?Vuex允许我们在store中定义getters(可以认为是store的计算属性)。getter接受state作为第一个参数:
// 在'store/index.js'中
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
},
// getters也可以接受其他getters作为第二个参数
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
getters会暴露为store.getters对象:
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
- 1
mapGetters辅助函数
他mapGetters辅助函数仅仅是将store中的getters映射到局部计算属性:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getters 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
])
//如果想给getter属性领取一个名字,可以对象形式:
mapGetters({
// 映射 this.doneCount 为 store.getters.doneTodosCount
doneCount: 'doneTodosCount'
})
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
Mutations
更改Vuex的store中的状态的唯一方法是提交mutation。Vuex的mutataions非常类似于事件:每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数就是我们实际进行状态更改的地方,他会接受state作为第一个参数:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
上边注册了一个类型为increment的mutation:“当触发一个类型为increment的mutation时,调用此函数。”实际使用时:store.commit('increment')
提交载荷(Payload)
载荷其实就是要传入vuex的数据对象啦。
你可以向store.commit传入额外的参数,即mutation的载荷(payload):
//注册mutation
mutations: {
// 这里的传入的数据对象payload就是载荷
increment (state, payload) {
state.count += payload.amount
}
}
//调用mutation的handler
store.commit('increment', {
amount: 10
})
//还可以使用对象风格来调用
store.commit({
type: 'increment',
amount: 10
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
Mutations需遵守Vuex的响应规则
既然Vuex的store中的状态时响应式的,那么当我们变更状态时,监视状态的vue组件也会自动更新。所以同样要遵守vue的响应式注意事项:
- 最好提前在store中初始化好所有属性
- 当需要在对象上添加新属性时:1.用Vue.set;2.用新对象替换老对象。
使用常量替代Mutation事件类型
使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式。这样可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然:
// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION'
// store.js
import Vuex from 'vuex'
import * as types from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
[types.SOME_MUTATION] (state) {
// mutate state
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
mutation必须是同步函数
一条重要的原则就是要记住 mutation 必须是同步函数
在组件中提交Mutations
你可以在组件中使用this.store.commit('type')提交mutataion,或者使用mapMutations辅助函数将组件中的methods映射为store.commit调用(需要在根节点注入store)。
import { mapMutations } from 'vuex'
export default {
// ...
methods: {
...mapMutations([
'increment' // 映射 this.increment() 为 this.$store.commit('increment')
]),
...mapMutations({
add: 'increment' // 映射 this.add() 为 this.$store.commit('increment')
})
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
Actions
Action类似于mutation,不同之处在于:
- Action提交的是mutataion,而不是直接变更状态。
- Action可以包含任意异步操作。
注册一个简单的Action:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。当我们在之后介绍到 Modules 时,你就知道 context 对象为什么不是 store 实例本身了。
解构:ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值。
//例如:赋值 var [a,b,c] = [1,2,3]
//例如:交换变量 [x,y] = [y,x]
//例如:函数参数解构:
// function add([x, y]){
// return x + y;
// }
// add([1, 2]); // 3
//实践中我们常用到 参数解构 来简化代码,下边
//的 { commit } 就用到了解构。
actions: {
increment ({ commit }) {
commit('increment')
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
这里解构的对象是context对象,也就是说context <==> { commit },这样写就可以用commit替代context.commit,简化代码。
分发Action
Action通过store.dispatch方法触发:store.dispatch('increment')
Actions 支持同样的载荷方式和对象方式进行分发:
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
我们可以在Action内部执行异步操作:
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在组件中分发Action
你在组件中使用 this.$store.dispatch('xxx') 分发 action,或者使用 mapActions 辅助函数将组件的 methods 映射为 store.dispatch 调用(需要先在根节点注入 store):
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment' // 映射 this.increment() 为 this.$store.dispatch('increment')
]),
...mapActions({
add: 'increment' // 映射 this.add() 为 this.$store.dispatch('increment')
})
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
组合Action
Modules
使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。
为了解决以上问题,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 的状态
vuex入门的更多相关文章
- vuex入门教程和思考 [转] 里面有几个实例
Vuex基础概念 vuex中涉及的概念主要有下面几点,下面做个简单的介绍和理解. Vuex 官方文档:https://vuex.vuejs.org/zh-cn/ 官网有介绍,也有个demo shopp ...
- vuex 入门
vuex.js 状态(数据)管理 在vue中当我们管理数据的时候比较乱,我们要用到下面的这个库,vuex.js Vuex介绍 每一个Vuex应用的核心就是store(仓库),他是用来存储数据的 &qu ...
- Vuex入门实践(中)-多module中的state、mutations、actions和getters
一.前言 上一篇文章<Vuex入门实践(上)>,我们一共实践了vuex的这些内容: 1.在state中定义共享属性,在组件中可使用[$store.state.属性名]访问共享属性 2.在m ...
- Vuex 入门指南
1.Vuex是什么? 我们还是像以往一样先看一看官方文档对此的解读(Vuex 是什么? · GitBook) Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的 ...
- Vuex入门(5)—— 为什么要用Action管理异步操作
Action 类似于 mutation,不同在于: 1.Action 提交的是 mutation,而不是直接变更状态. 2.Action 可以包含任意异步操作. 官方给的定义我没什么意见,事实上我通过 ...
- vuex入门教程和思考
Vuex是什么 首先对于vuex是什么,我先引用下官方的解释. Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可 ...
- vuex入门文档
如果你在使用 vue.js , 那么我想你可能会对 vue 组件之间的通信感到崩溃 . 我在使用基于 vue.js 2.0 的UI框架 ElementUI 开发网站的时候 , 就遇到了这种问题 : 一 ...
- Vue2.0 探索之路——vuex入门教程和思考
Vuex是什么 首先对于vuex是什么,我先引用下官方的解释. Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式.它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可 ...
- [转] Vuex入门(2)—— state,mapState,...mapState对象展开符详解
1.state state是什么? 定义:state(vuex) ≍ data (vue) vuex的state和vue的data有很多相似之处,都是用于存储一些数据,或者说状态值.这些值都将被挂载 ...
随机推荐
- 转: JavaScript 获取对象属性和方法
一.获取对象属性和方法 Object.keys()for in 返回对象的可枚举属性和方法的名称数组. Object.getOwnPropertyNames() 返回的数组的所有属性(可枚举或不可枚举 ...
- Android开发Toast Notifications
Android开发Toast Notifications 关键类 Toast toast通知是一种在窗口表面弹出的消息.它只占用信息显示所需的空间,用户当前的activity仍保持可见并可交互.该通知 ...
- Tomcat启动过程源码解读
根据Tomcat源码来看一下Tomcat启动过程都做了什么 部分代码为主要流程代码,删去了try-catch以及一些校验逻辑,方便理解主流程 先来一张启动过程时序图,了解一下启动顺序 Tomcat启动 ...
- 快速了解Druid——实时大数据分析软件
Druid 是什么 Druid 单词来源于西方古罗马的神话人物,中文常常翻译成德鲁伊. 本问介绍的Druid 是一个分布式的支持实时分析的数据存储系统(Data Store).美国广告技术公司Met ...
- 关于用wubi安装Ubuntu,总是提示“没有定义根文件系统”的问题
用diskgenius测试一下分区问题,就发现一些错误,所以怀疑可能就是因为这个分区参数错误导致WUBI安装不成功,费了大力气转移数据后,重新对硬盘分区,这里称赞一下diskgenius,的确不错,当 ...
- INS-30002 口令和确认口令不同
1.错误描述 2.错误原因 由截图上的提示,可以看出是管理口令和确认口令不一致 3.解决办法 重新输入密码
- hdu5937 Equation
题解其实网上有 突然有点感想 为什么可以用搜索或状压,因为方案数很有限,它要求每种方案不同就意味着搜索的次数也一定,所以现在就应该坚定往这方面想,找部分方案的贪心.这和上一题一样,都是先暴力,后面处理 ...
- httpclient的get带参不带参post带参不带参的简单应用
一,基础的的应用 1.1,get的无参请求 @Test public void doGet() throws Exception { //创建一个httpclient对象 CloseableHttpC ...
- docker学习系列(一):docker 基础
一.简介 开发当中比较麻烦的问题在于软件配置,每个人的机械以及系统都不尽相同,程序需要运行在系统当中需要配置好相应的系统以及各种依赖的组件,但是很多时候由于各种软件依赖包的版本,系统兼容性问题会导致程 ...
- 一篇关于PHP性能的文章
一篇关于PHP性能的文章 昨晚清理浏览器收藏夹网址时,发现了http://www.phpbench.com/,想起来应该是2015年发现的一个比较性能的文章,我就点进去看了看,发现还是全英文耶,刚好最 ...