vuex详解
vuex
vuex的定义:
Vuex是Vue.js应用程序的状态管理模式+库。 vuex采用集中式存储所有组件的数据状态,并且组件状态和后台数据是响应的。
vuex解决的问题:
1)多个视图依赖于同一状态
2)来自不同视图的行为需要变更同一状态
Vuex则是把组件的共享状态抽取出来,以一个全局单例模式管理
同时,通过定义和隔离状态管理中的各种概念并强制遵守一定的规则,代码变得更结构化、易维护
以上就是vuex的思想
使用:
script 引入
<script src="/path/to/vue.js"></script>
<script src="/path/to/vuex.js"></script>
包管理安装: npm i vuex -S
在一个模块化的打包系统中,必须通过显式地通过Vue.use() 来安装vuex:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
vuex的五个核心概念:
State,Getter,Mutation,Action,Module,
vuex主要有四个部分:
- state:包含了
store
中存储的各个状态。 - getter: 类似于 Vue 中的计算属性,根据其他 getter 或 state 计算返回值。
- mutation: 一组方法,是改变
store
中状态的执行者, 只能是同步操作 。 - action: 一组方法,其中可以 包含异步操作 。
vue单页面应用中使用
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
getter: {
doneTodos: (state, getters) => {
return state.todos.filter(todo => todo.done)
}
},
mutations: {
increment (state, payload) {
state.count++
}
},
actions: {
addCount(context) {
// 可以包含异步操作
// context 是一个与 store 实例具有相同方法和属性的 context 对象
}
}
})
// 注入到根实例
new Vue({
el: '#app',
// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
store,
template: '<App/>',
components: { App }
})
State 存储应用中需要共享的状态,存放数据
const Counter = {
template: `<div>{{ count }}</div>`,
computed: { count () { return this.$store.state.count // count 为某个状态 } }
}
Getter Store 的计算属性
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) } } })
通过属性访问
我们可以很容易在任何组件中使用他
computed: {
doneTodosCount () {
return this.$store.getters.doneTodosCount
}
}
通过方法访问
也可以通过让 getter 返回一个函数,来实现给 getter 传参。在对 store 里的数组进行查询时非常有用。
getters: {
// ...
getTodoById: (state) => (id) => {
return state.todos.find(todo => todo.id === id)
}
}
store.getters.getTodoById(2) // -> { id: 2, text: '...', done: false }
注意:getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果。
mutations 改变状态的执行者 只能同步的更改状态 不能出现异步的方法
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
提交载荷(Payload)
// ...
mutations: {
increment (state, n) {
state.count += n
}
}
this.$store.commit('increment', 10)
其中,第一个参数是 state
,后面的参数是向 store.commit
传入的额外的参数,即 mutation 的 载荷(payload) 。
store.commit
方法的第一个参数是要发起的 mutation
类型名称,后面的参数均当做额外数据传入 mutation
定义的方法中。
规范的发起 mutation
的方式如下:
// 以载荷形式
store.commit('increment',{
amount: 10 //这是额外的参数
})
// 或者使用对象风格的提交方式
store.commit({
type: 'increment',
amount: 10 //这是额外的参数
})
额外的参数会封装进一个对象,作为第二个参数传入 mutation
定义的方法中。
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
Action 异步方法(异步的更改状态)
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
Action与mutation的区别
action提交的是mutation,而不是直接变更状态
action可以包含任意异步操作,而mutation只能且必须是同步操作
module 模块化
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
这时我们可以将 store 分割为 模块(module) ,每个模块拥有自己的 state
、 getters
、 mutations
、 actions
、甚至是嵌套子模块——从上至下进行同样方式的分割。
代码示例:
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 的状态
欢迎各位大佬补充!