vuex的简单使用
当多个视图或者组件需要数据共享的时候,vuex就出现了。vuex是vue官方提供的响应式数据存储插件。一般用来存放全局变量,共享数据,配置项数据。下面我们从多个方面来使用。
[loginview]
引入vuex
在使用之前,我们当然需要先引入vuex啦,先要使用yarn add vuex
安装vuex依赖,然后在main.js
中引入import store from './store'
,为了方便使用,我们可以把store
注入vue实例根节点
···
new Vue({
store,//注入
router,
render: h => h(App),
}).$mount('#app')
···
vuex的state基本使用
state顾名思义就是用来存储状态用的,在实际使用的时候不止可以用来存储状态,像数组,对象也是可以存储的。
- 用法1,直接在
store.js
里面声明自己需要的变量。
```js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
menu:[],//这就是自己定义的变量
version:''
}
})
```
我声明了一个菜单数组和一个版本号(字符串类型)。多个变量,可以用,
隔开就行了。
调用变量:像this.$store.state.menu
或者this.$store.state['menu']
这样。我们在test1.vue
中尝试一下,修改为:
<template>
<div>
<div>Test1视图</div>
<!--页面读取-->
<p>version={{$store.state.version}}</p>
<p>menu={{$store.state.menu}}</p>
<p>mVersion={{mVersion}}</p>
<p>mMenu={{mMenu}}</p>
</div>
</template>
<script>
export default {
data(){
return {
mVersion:'',
mMenu:[],
}
},
mounted() {
//赋值
this.$store.state.menu = ['menu1', 'menu2']
this.$store.state.version = '1.0'
this.mVersion = this.$store.state.version
this.mMenu = this.$store.state.menu
}
}
</script>
我们对stote里面的变量进行赋值,然后再读取出来赋值给我们本地的变量,观察本地变量和store里面的变量是否一致,现在页面输出:

符合我们的预期。
- 用法2,我们不直接声明变量,我们可以动态的创建出来。因为state本身也是一个对象,动态创建,相当于给这个对象加一个
key
。注意了,如果我们使用这种方式创建:
```js
this.$store.state['menu'] = ['menu1', 'menu2']
this.$store.state['version'] = '1.0'
```
是不支持响应式的,vue无法监听到数据的变化,就无法更新页面,这取决于vue框架。但是vue提供了set
方法,我们要这样写:
```js
this.$set( this.$store.state,'menu',['menu1', 'menu2'])
this.$set( this.$store.state,'version','1.0')
```
调用方式和用法1
一样。
vuex的getter基本使用
vuex考虑到开发者会根据一种状态派生出其他的状态,设计了getter,这玩意有点像computed属性,同样支持缓存。修改store.js
:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
persons: [{name: '小米', age: 10}, {name: '张珊', age: 20}]
},
getters:{
personCount(state){
return state.persons.length
}
}
})
我们在getters
定义一个专门用来获取persons
数组长度的属性personCount
。
调用方式也很简单:
<template>
<div>
<div>Test1视图</div>
<!--页面模板中调用不需要this-->
<p>personCount={{$store.getters.personCount}}</p>
</div>
</template>
<script>
export default {
mounted(){
//代码里面调用要加上this
console.log(this.$store.getters.personCount)
}
}
</script>
它还可以实现参数传递,上面我们是通过属性调用,如果使用方法调用,那么他就可以传参了。代码变成:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
persons: [{name: '小米', age: 10}, {name: '张珊', age: 20}]
},
getters: {
personCount: (state) => (age) => {
return state.persons.filter(p => p.age===age).length
}// 定义多个属性,用逗号隔开
}
})
现在我们的personCount
支持查询某个年龄的人数了。于此同时,调用的地方需要修改:
<template>
<div>
<div>Test1视图</div>
<p>personCount={{$store.getters.personCount(10)}}</p>
</div>
</template>
<script>
export default {
mounted(){
console.log(this.$store.getters.personCount(10))
}
}
</script>
vuex的mutation基本使用
之前我们修改store.state
中的数据,都是直接对变量赋值,这种方法其实不太友好,虽然很暴力很直接。通过mutation
提交更加符合vue框架。我们先修改store.js
:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
persons: [{name: '小米', age: 10}, {name: '张珊', age: 20}]
},
getters: {
personCount: (state) => (age) => {
return state.persons.filter(p => p.age===age).length
}
},
mutations:{
addPerson(state,person){
state.persons.push(person)//push是数组操作方法,在数组尾部插入一个元素
}
}
})
我们加了一个addPerson
在mutations
,这玩意不是一个方法,因为不能直接调用,你必须要这样调用this.$store.commit('addPerson',{name: '小刚', age: 10})。
注意: mutation
中不要使用异步代码。
vuex的Action基本使用
Action
类似于 mutation
,不同在于:
Action
提交的是mutation
,而不是直接变更状态。Action
可以包含任意异步操作。
我们修改store.js
:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
persons: [{name: '小米', age: 10}, {name: '张珊', age: 20}]
},
getters: {
personCount: (state) => (age) => {
return state.persons.filter(p => p.age===age).length
}
},
mutations:{
addPerson(state,person){
state.persons.push(person)//push是数组操作方法,在数组尾部插入一个元素
}
},
actions:{
addPerson(context,person){
setTimeout(()=>{
context.commit('addPerson',person)
},1000)
}
}
})
我们在actions
节点中定义一个名为addPerson
的action,然后故意延迟1s执行。同时我们把test1.vue
修改为:
<template>
<div>
<div>Test1视图</div>
<!--页面读取-->
<p>personCount={{$store.getters.personCount(10)}}</p>
</div>
</template>
<script>
export default {
mounted(){
this.$store.dispatch('addPerson',{name: '小刚', age: 10})
}
}
</script>
刷新页面,我们发现页面上personCount
一开始是1,过1s后就变成2了。
vuex的module基本使用
随着我们的项目越来越大,用到的共享变量越来越多,store变得越来越复杂和臃肿,那么我们有必要分割成不同模块。我们先修改store.js
:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//模块1
const person = {
state: {
persons: [{name: '小米', age: 10}, {name: '张珊', age: 20}]
},
getters: {
personCount: (state) => (age) => {
return state.persons.filter(p => p.age === age).length
}
},
mutations: {
addPerson(state, person) {
state.persons.push(person)//push是数组操作方法,在数组尾部插入一个元素
}
},
actions: {
addPerson(context, person) {
setTimeout(() => {
context.commit('addPerson', person)
}, 1000)
}
}
}
//模块2
const phone = {
state: {
phone: [{name: '小米'}, {name: '苹果'}]
},
actions: {
addPerson(context, person) {
setTimeout(() => {
context.commit('addPerson', person)
}, 1000)
}
}
}
export default new Vuex.Store({
modules: {
person: person,
phone: phone
}
})
我们声明了2个模块person
和phone
。
这个时候我们该如何调用呢?
console.log(this.$store.state.person)
console.log(this.$store.state.phone)
this.$store.dispatch('addPerson',{name: '小刚', age: 10})
this.$store.commit('addPerson',{name: '小刚', age: 10})
console.log(this.$store.getters.personCount(10))
state
的调用需要加上模块的名称,action
,mutation
,getter
的调用还是保持一样,只是需要注意,如果不同的模块中有相同名称的action
,mutation
,getter
都会被触发。默认情况下,模块内部的 action
,mutation
,getter
是注册在全局命名空间的。这种特性有时候也是有用的。如果你需要区分不同模块,那么需要把namespaced: true
,当模块被注册后,它的所有action
,mutation
,getter
都会自动根据模块注册的路径调整命名。调用方式也会发生变化:
console.log(this.$store.state.person)//不变
console.log(this.$store.state.phone)//不变
this.$store.dispatch('person/addPerson',{name: '小刚', age: 10})
this.$store.commit('person/addPerson',{name: '小刚', age: 10})
console.log(this.$store.getters['person/personCount'](10))
想要深入了解,请查阅官方手册。
vuex和computed的联合使用
利用computed可以简化vuex的调用,使得代码不用每次都this.$store.state.xxx
。
比如:
<template>
<div>
<div>Test1视图</div>
<!--页面读取-->
<p>personCount={{personCount}}</p>
</div>
</template>
<script>
export default {
mounted(){
this.$store.dispatch('addPerson',{name: '小刚', age: 10})
},
computed:{
personCount(){
return this.$store.getters.personCount(10)
}
}
}
</script>
注意计算属性没法直接传值。如果你非要传值也是有办法的,改成这样:
···
personCount(){
return function(age){
return this.$store.getters.personCount(age)
}
}
···
本质上返回了一个方法,感觉有点投机取巧,在调用的时候只能这样调了:
···
this.personCount(10)
···
这和直接在metheds
里面定义一个方法personCount
:
···
methods:{
personCount(age){
return this.$store.getters.personCount(age)
}
}
···
其实效果是一样的。不是很推荐这种投机的方法。尽量在设计角度去规避这种写法。
[/loginview]