深入了解Vue中Vuex的用法
作者:格斗家不爱在外太空沉思
前言
Vuex是做什么的?官方的解释是一个专为vue.js应用程序开发的状态管理模式,采用集中式存储管理应用所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。看完是不是一脸问号,状态管理到底是什么?其实可以将其看成把需要多个组件共享的变量全部存储在一个对象里,将这个对象放在最顶层的vue实例中,让其他组件可以使用
安装
在脚手架里,我们可以通过创建项目时勾选vuex的选项,系统会自动创建
也可以通过npm下载npm install vuex --save
配置
新建一个store文件夹->新建index.js进行配置,如果是通过脚手架创建vuex无需配置
import Vue from 'vue' import Vuex from 'vuex' //安装插件 Vue.use(Vuex) //创建对象 const store=new Vuex.Store({ state:{ }, mutations:{ }, actions:{ }, getters:{ }, modules:{ } }) //导出store对象 export defaule store
main.js中引入
import store from 'store路径' new Vue({ el:'#app', store,//Vue.prototype.$store=store render: h => h(App) })
核心概念
在Vuex里有几个比较核心的概念:
State
Mutations
Getters
Actoins
Modules
state
state用来保存状态,类似data,例如在state里保存一个count状态,在任意组件里都可以拿来使用
state:{ count:10000 } //任意组件里使用,直接展示 <div>{{$store.state.count}}</div>
如何修改state
<div>{{$store.state.count}}</div> <button @click="$store.state.count++">+</button> <button @click="$store.state.count--">-</button>
那么状态需要修改时怎么做呢?很多人会像上面一样修改,但是这样后续调试的时候会出问题的,对于怎么修改,官方给出了一张图,如下:
从这张图的state开始顺着箭头走,state提供数据给vue组件,vue组件想要修改state得发布一个行为actions,发布之后提交到mutations里,在mutations里修改state。听起来是不是更复杂?
为什么官方希望我们这么做,图里有一个Devtools,这是vue开发的一个浏览器插件,可以帮助我们记录修改后的state状态,可以进行跟踪,但是直接在vue组件里修改state,devtools是记录不到的
既然devtools是在mutations进行记录追踪,那actions是干嘛的?其实我们可以跳过actions,直接在vue组件里通过mutations修改state
当我们修改的时候有异步操作的时候,才需要通过actions操作完后提交到mutations再进行同步操作,因为devtools是跟踪不到异步操作的
下载devtools浏览器插件地址
mutations的基本使用
当我们直接去修改state里的状态时,devtools并不会记录下来
那我们如何通过mutations修改?
mutations:{ inc(state){//默认传入一个state,对应上面的state对象 state.count++ }, dec(state){ state.count-- } } //方法1 <div> <div>{{$store.state.count}}</div> <button @click="$store.commit('inc')">+</button>//通过commit方法传入mutations里定义的方法的名字 <button @click="$store.commit('dec')">-</button> </div> //方法2 methods: { inc(){ this.$store.commit('inc')//通过commit方法传入mutations里定义的方法的名字 }, dec(){ this.$store.commit('dec') } }, <div> <div>{{$store.state.count}}</div> <button @click="inc">+</button> <button @click="dec">-</button> </div>
通过mutations修改state,devtools会追踪到并且记录下来,我们开发时就可以通过历史记录来追踪发现哪一步发生了错误
mutations传递参数
例如:当上面案例再添加n个按钮去加或减不同的值,我们再去创建n个方法来修改,显然这是不对的,我们只要定义一个方法,传入对应的参数就可以去实现这样的效果,那我们怎么在mutations里传递参数呢?
mutations:{ add(state,count){//接收参数 state.count+=count }, subtract(state,count){ state.count-=count } }, methods: { add(count){ this.$store.commit('add',count)//传递参数 }, subtract(count){ this.$store.commit('subtract',count) } }, <div> <div>{{$store.state.count}}</div> <button @click="add(5)">+5</button> <button @click="subtract(5)">-5</button> </div>
getters的使用
getters类组件里的计算属性,什么是计算属性?当数据经过一系列变化之后再展示就是计算属性了,getters也是一样,那如何使用呢?
getters:{ power(state){//默认传入一个state,对应上面的state对象 return state.count*state.count } } <div>平方:{{$store.getters.power}}</div>
actions的使用
上面已经说过mutations中的方法必须是同步方法,我们在mutatoins里用setTimeout模拟一下异步操作看看会发生什么
//store.js state:{ name:'aaa' }, mutations:{ updateName(state){ setTimeout(() => { state.name='bbb' }, 1000); } }, //组件 <div>{{$store.state.name}}</div> <button @click="updateName">修改名字</button> methods: { updateName(){ this.$store.commit('updateName') } },
我们可以发现点击修改名字按钮后页面显示的名字发生了变化,但是devtools没有追踪记录到,还是'aaa',所以mutations中的方法必须是同步方法
那当我们有异步操作的时候怎么办?就得通过actions来先进行异步操作后提交到mutations再进行同步操作:
//store.js state:{ name:'aaa' }, mutations:{ updateName(state){ state.name='bbb' } }, actions:{ updateInfo(context){//上下文,当前可以理解为store对象 setTimeout(() => { context.commit('updateName')//不能直接修改,修改state的唯一途径就是mutations }, 1000); } }, //组件 <div>{{$store.state.name}}</div> <button @click="updateName">修改名字</button> methods: { updateName(){ this.$store.dispatch('updateInfo')//调用actions里的方法是dispatch } },
修改完之后点击按钮等待一秒,devtools可以追踪记录到了
modules的使用
当应用变得非常复杂时,store对象就会变得非常臃肿,为了解决这个问题,Vuex允许我们将store分割成模块(Modules),每个模块拥有自己的state,getters,mutations,actions等,下面是分割模块的例子:
const moduleA={ state:{ test:'模块a的state' }, mutations:{}, getters:{}, actions:{} } const moduleB={ state:{}, mutations:{}, getters:{}, actions:{} } const store=new Vuex.Store({ modules:{ a:moduleA, b:moduleB } })
模块分好之后怎么调用里面的state,getters之类呢?除state之外其他getters,mutations调用和之前一样,但是actions里只能commit自己模块里的mutaions,state调用要加上模块的名字,例如调用上面的state就是<div>{{$store.state.a.test}}</div>
,为什么会这样呢,我们可以打开devtools工具看一下就知道了
模块a会被放在state里面,所以调用的时候要加上模块的名字
以上就是深入了解Vue中Vuex的用法的详细内容,更多关于Vue Vuex的资料请关注脚本之家其它相关文章!