什么是Vuex?
用2句话概括:
- 主要应用于Vue.js中管理数据状态的一个库
- 通过创建一个集中的数据存储,供程序中所有组件访问
当然这么说肯定还是有所不懂,这里我就用单一使用vue.js和使用vuex.js场景的不同进行对比讲解
单一使用Vue.js的场景
在单一使用vue.js的场景中,我们难免要在不同的组件中互相传值。在该场景中,由一个根组件,两个父组件再各自拥有一个子组件,我们如果使用prop的属性传值,在这个详情组件需要使用添加组件中的某个值时,我们需要不停的触发某个事件将这个值一层一层一层一层地沿着这个路径传过去,这样能实现将值传递给详情组件,但这是相当的麻烦(鬼知道我当初不知道vuex为了传值头有多大)。现在让我们看下vuex.js场景下的效果
使用Vuex.js的场景
我们将使用专门的store存储所有的数据,如果我们需要取到组件二或更深一级的子组件的某个数据我们可以直接使用getter方法直接拿到其中的数据。如果我们需要向store中添加或更改某个数据,我们可以用mutation或直接$store.state的形式直接跨过父组件向store中直接添加或更改数据。就好比一个仓库,所有人能直接跨过上级拿到仓库中的某个你所需要的东西,这无疑是在我们使用vue开发项目时,相当省时省力的办法。
Vuex的使用场景
- 涉及到非父子关系的组件,例如兄弟关系、祖孙关系,甚至更远的关系组件之间的联系
- 中大型单页应用,考虑如何更好地在组件外部管理状态
相信大家在看完上面vuex的基本介绍后,心里对它使用场景也有了一个大概的想法。
总而言之,在页面数据结构比较复杂,数据和组件分离,分别处理,组件量较大的情况下,那么使用 Vuex 是非常合适的。
Vuex的安装配置
在使用vue-cli脚手架创建项目后
npm install vuex
进入项目安装vuex,安装完成后,在项目的文件夹src中再新建一个文件夹store,文件夹中新建文件store.js(命名为本人习惯)。
store.js
//引入vue和Vuex
import Vue from 'vue'
import Vuex from 'vuex'
//引入之后,对vuex进行引用
Vue.use(Vuex)
main.js
import {store} from './store/store'
new Vue({
store:store,//使用store
el: '#app',
router,
components: { App },
template: '<App/>',
})
在main.js 中引入vuex文件
到此为止,vuex的引入就算是成功了。
基本概念
State
现在回到我们的store.js中
//创建且声明一个对象
export const store = new Vuex.Store({
state:{
isShow:true,
items:[
{
name:"张三",
num:"1"
},
{
name:"李四",
num:"2"
},
{
name:"王五",
num:"3"
}
]
}
})
这里不同于文档中的写法,我这里直接将创建声明简写成一段代码(个人更偏好这样写)。在state中填写外部组件需要的数据。外部组件中调取数据:
computed:{
itemList(){
return this.$store.state.items
}
},
//这里有两种办法
//p在computed的itemList方法中循环
<p v-for="item in itemList">{{item.num}}{{item.name}}</p>
//p直接指向store中的state的items数组
<p v-for="item in this.$store.state.items">{{item.num}}{{item.name}}</p>
可以通过computed中的方法获取数据,也可以直接使用this.$store.state。
Getters
getters乍一看也是获取数据,但是在获取之前它多了一个步骤:计算过滤获取的数据并返回过滤完成后的数据。如果多个组件需要用到筛选后的数据,那我们就必须到处重复写该计算属性函数;或者将其提取到一个公共的工具函数中,并将公共函数多处导入。
store.js
getters:{
numChange(state){
return state.items.forEach(item=>{
item.num+=100
})
}
}
组件中:
//写法一:
<p v-for="item in this.$store.getters.numChange">{{item.num}}{{item.name}}</p>
//写法二:
<button @click="numTurn">改变数字</button>
computed:{
numChange(){
return this.$store.getters.numChange
}
},
p标签在computed中返回getters数据的中循环,数据显示出来便直接是计算完成后的数据
Mutations
我们可以使用mutations配合vuex提供的commit方法来修改state中的状态
store.js
export const store = new Vuex.Store({
state:{
isShow:false,
myData:'',
items:[
{
name:"张三",
num:1
},
{
name:"李四",
num:2
},
{
name:"王五",
num:3
}
]
},
mutations:{
//定义一个函数动态修改state的状态值
numTurn(state){ /这里的state代表上面的State
state.items.forEach(item=>{
item.num+=100
})
}
}
})
组件中:
//写法一:
<button @click="$store.commit('numTurn')">改变数字</button>
//写法二:
<button @click="numTurn">改变数字</button>
methods:{
numTurn(){
this.$store.commit('numTurn')
}
}
两种写法原理是一样的,都能实现效果。注意:mutations中的方法需要commit配合回调实现,而不再是$store.mutation,且mutations只能处理同步函数,那如果需要处理异步操作怎么办?
Action
如文档中所说,Action类似于Mutations,不同在于:
- Aciton提交的是mutation,而不是直接变更状态
- Action可以包含任何异步操作
那也就是说,如果我们是需要任意的异步操作,那就需要在Action中实现