介绍
- Vuex 是一个专为 Vue.js
应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到
Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel
调试、状态快照导入导出等高级调试功能。
1.安装
1.直接下载/CDN引用
2. https://unpkg.com/vuex
3. 在 Vue 之后引入 vuex 会进行自动安装:
<script src='/path/to/vue.js'></script>
<script src='/path/to/vuex.js'></script>
4.npm安装
npm install vuex --save
5.yarm 安装
yarn add vuex
6.在一个模块化的打包系统中,您必须显式地通过 Vue.use() 来安装 Vuex:
import Vue from 'vue'
import Vue from 'vuex'
Vue.use(Vuex)
2.什么是“状态管理模式”
-
从简单的vue计数应用开始: new Vue({
// state
data () {
return {
count: 0
}
},
// view
template:<div>{{ count }}</div>
,
// actions
methods: {
increment () {
this.count++
}
} }) -
这个状态自管理应用包含以下几个部分:
state,驱动应用的数据源;
view,以声明方式将 state 映射到视图;
actions,响应在 view 上的用户输入导致的状态变化。 -
但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
多个视图依赖于同一状态。
来自不同视图的行为需要变更同一状态。
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。这就是 Vuex 背后的基本思想。
3. 简单使用
- 每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
例如创建一个最简单的store,提供初始的state对象和mutation: - const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
}) - 现在,你可以通过 store.state 来获取状态对象,以及通过 store.commit 方法触发状态变更:
- store.commit(‘increment’)
console.log(store.state.count) // -> 1 - 再次强调,我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。
由于 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性中返回即可。触发变化也仅仅是在组件的 methods 中提交 mutation。
4.State
- 提供唯一的公共数据源,所有共享数据都要统一放到Store的State中进行存储
- 创建store数据源,
const store = new Vuex.Store({
state:{
name:“张三”
}
}) - 组件访问State中的数据
第一种
this. s t o r e . s t a t e . 全 局 数 据 名 称 t h i s . store.state.全局数据名称 this. store.state.全局数据名称this.store.state.name
第二种
1.从vuex 中按需导入mapState 函数
import {mapState} from “vuex”
2.通过刚才导入的mapState函数,将当前组件需要的全局数据,映射为当前组件的computed计算属性
computed:{
…mapState([‘name’])
} - 单一状态树
state里面的状态
state:{
name:“张三”
}
使用计算属性获取最简单
computed:{
name(){
return this.$store.state.name
}
5.注意在其他方法中不要直接修改state里面的属性,想要修改请使用Mutation
5.mutation
-
用于变更Store中的数据
-
提交更新数据的方法,必须是同步的(如果需要异步使用action)
-
只能通过mutation变更store数据,不可以直接操作Store中的数据
-
通过这个方式虽然操作起来稍微繁琐一些,但是可以集中监听所有数据的变化
-
注意:里面不要执行异步操作
-
第一种触发
//定义mutation
const store = new Vuex.Store({
state:{
count:0
},
mutations:{
//第一个参数是state对象
add(state){
//变更状态
state.count++
}
}
})//触发mutation
methods:{
aa(){
//add是mutation里面的方法
this.$store.commit(‘add’)
}
}
可以在触发mutation时传递参数//定义mutation
const store = new Vuex.Store({
state:{
count:0
},
mutations:{
//第一个参数是state对象
//va自定义的参数
add(state,va){
//变更状态
state.count += va
}
}
})//触发mutation
methods:{
aa(){
//add是mutation里面的方法
//携带参数 2
this.$store.commit(‘add’,2)
}
} -
第二种触发 从 vuex中按需导入mapMutations 函数
import {mapMutations} from 'vuex' 将制定的mutations函数,映射为当前组件的methods函数中 methods:{ ...mapMutations(['add','ooo']) }
-
commit
用来触发mutation里面方法用的
this.$store.commit(‘mutations方法名’,值)
6.action
-
//定义action
const store = new Vuex.Store({
state:{
count:0
},
mutations:{
add(state){
state.count++
}
},
actions:{
//第一个参数是context
addAsync(context){
setTimeout(()=>{
context.commit(‘add’)
},1000)
}
}
}) -
//触发action
methods:{
abc(){
//addAsynce 是actions里面的方法
this.$store.dispatch(‘addAsynce’)
}
}
第二种触发
1.从 vuex中按需导入mapActions 函数import {mapActions} from 'vuex' 2. 将制定的mapActions函数,映射为当前组件的methods函数中 methods:{
…mapAction([‘addAsync’])
} -
dispatch
用来触发action里面的方法
this.$store.dispatch(‘addAsynce’,值) -
携带参数
//定义action
const store = new Vuex.Store({
state:{
count:0
},
mutations:{
add(state,num){
state.count+=num
}
},
actions:{
//第一个参数是context
addAsync(context,num){
setTimeout(()=>{
context.commit(‘add’,num)
},1000)
}
}
})
methods:{
abc(){
//addAsynce 是actions里面的方法
this.$store.dispatch(‘addAsynce’,4)
}
}
7.getter
- 从基本数据state派生的数据,相当于state的计算属性,具有返回值的方法
- 会返回一个新数据,不会影响到state里面的老数据
- store中的数据发生变化.getter的数据也会跟着变化
- const store = new Vuex.store({
state:{
count:0
},
getters:{
userId1:function(state){
return state.count * 2
}
}
}) - 第一种使用方式 this.$store.getters.userId1
- 第二种
import {mapGetters} form ‘vuex’
computed:{
…mapGetters([‘userId’])
} - mapGetters 辅助函数
辅助函数仅仅是将 store 中的 getter 映射到局部计算属性
第一步 引入 import { mapGetters } from ‘vuex’
第二步
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
//就可以以访问计算属性的形式去访问这些方法了
…mapGetters([
‘doneTodosCount’, //是getters里面的方法
‘anotherGetter’,
// …
])
}
第三步使用
{{doneTodosCount}}
8.modules
- 模块化vuex
- 可以让每一个模块拥有自己的state,mutation,action,getters,使得结构非常清晰,方便管理