Vuex的使用
简单的简历一个store仓库
在文件夹store下面的index.js写入如下代码。
import Vue from 'vue'
import Vuex from 'vuex'
// 全局注册插件
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
age: 18
}
})
上面约等于在状态管理中全局挂在了该store,需要使用的时候可以直接调来使用。
获取状态
<template>
<div>
<p>the count is {{count}}</p>
<p>the age is {{age}}</p>
</div>
</template>
<script>
export default {
data() {
return {
count: 0,
age: 0
}
},
mounted() {
console.log(this.$store) // 打印出store 可以看到里面有个state,可以来获取state中的参数然后给初始化的data进行赋值
this.count = this.$store.state.count
this.age = this.$store.state.age
}
}
</script>
上面代码中是通过this.$store.state.count来获取的状态
mapState获取状态
<template>
<div>
<p>the count is {{count}}</p>
<p>the age is {{age}}</p>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
// count: 10,
// age: 0
}
},
mounted() {
console.log(this.$store)
// this.count = this.$store.state.count
// this.age = this.$store.state.age
},
methods: {
getState () {
console.log(this.count) // 获取count的值
}
},
computed: {
...mapState(['count', 'age']) // 通过辅助函数来获取相关的,参数为一个数组,数组内字符串表示获取的状态,获取后直接会挂载到this上面,通过this.count即可获取
}
}
</script>
上面说了获取,下面来说明如何实现修改状态。
修改状态
// store/index.js 如下修改
export default new Vuex.Store({
state: {
count: 0,
age: 18
},
mutations: {
addCount (state, upload) { // 用来触发修改的函数,upload为传递过来的参数
state.count += upload // 官方建议载荷upload应该为对象 次数使用值
}
}
})
// 调用的组件
<template>
<div>
<p>the count is {{count}}</p>
<p>the age is {{age}}</p>
<button @click='getState'>count</button>
<button @click='changeCount(10)'>addCount</button>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
data() {
return {
// count: 10,
// age: 0
}
},
mounted() {
// console.log(this.$store)
// this.count = this.$store.state.count
// this.age = this.$store.state.age
},
methods: {
getState () {
console.log(this.count)
},
changeCount (x) {
this.$store.commit('addCount', x)// 使用commit来提交mutation,从而修改状态
}
},
computed: {
...mapState(['count', 'age'])
}
}
</script>
其实修改状态的方法只有一种,就是提交mutation
mutation辅助函数
// (为了代码完整,复制可用,使用的完整子组件代码)
<template>
<div>
<p>the count is {{count}}</p>
<p>the age is {{age}}</p>
<button @click='getState'>count</button>
<button @click='changeCount(10)'>addCount</button>
<button @click='changeAge(10)'>addAge</button>
</div>
</template>
<script>
import { mapState, mapMutations } from 'vuex'
export default {
data() {
return {
// count: 10,
// age: 0
}
},
mounted() {
// console.log(this.$store)
// this.count = this.$store.state.count
// this.age = this.$store.state.age
},
methods: {
getState () {
console.log(this.count)
},
...mapMutations({
changeCount: 'addCount', // 将mutation的addCount映射为这里的changeCount
changeAge: 'addAge' // addAge映射为changeAge
})
// changeCount (add) {
// this.$store.commit('addCount', add)
// }
},
computed: {
...mapState(['count', 'age'])
}
}
</script>
action的使用
// 下列代码中写到mutations中
resetAge (state) {
console.log('我是被触发了的')
setTimeout(() => {
state.age = 0
}, 3000) // 三秒后重置年龄
}
// 添加一个button来触发
<button @click="zeroAge">age0</button>
// 组件内map函数在映射一个zeroAge
...mapMutations({
changeCount: 'addCount',
changeAge: 'addAge',
zeroAge: 'resetAge'
})
本次测试中完全没问题,状态被修改 为0,并且Vue.js devtools中的状态还是被修改了,但是可能会导致调试工具状态不更新的问题。根据官方建议:异步操作在action中使用
使用方法如下:
// mutation 中添加
zeroAge(state) {
console.log(state)
state.age = 0
}
// action中添加出发mutation的方法
actions: {
resetAge (content) {
console.log('content', content)
setTimeout(() => {
content.commit('zeroAge')
}, 3000)
}
}
// 组件中调用方法使用this.$store.dispatch('触发action事件的名字') button中使用该事件(zeroAge)
zeroAge() {
this.$store.dispatch('resetAge')
}
注意:修改状态只能在mutations中,因此actions知识用来异步触发mutations的
使用辅助函数mapActions
// 引入这里就不写了,直接在methods里面添加
...mapActions({
zeroAge: 'resetAge' // 将action 映射为方法zeroAge, 使用即可触发。
})
getters的使用
// 这里在state中添加一个数组,利用getters来获取过滤后的数据
state: {
count: 0,
age: 18,
list: [55, 66, 77, 88, 87, 25]
},
getters: {
getList(state) {
eturn state.list.filter(item => item > 75)
}
}
// 组件中进行使用
computed: {
...mapState(['count', 'age']), //之前的代码
getList() { // 直接可以使用getList数据
console.log(this.$store.getters.getList)
return this.$store.getters.getList
}
}
// 渲染模板中使用getList来渲染过滤后的数据
<p v-for="(item, index) in getList" :key="index">{{item}}</p>
mapGetters的使用和mapState相同,此处不再赘述。
最后的module
这个模块十分重要,对于程序的模块化管理和可读性都有很大帮助
// 这里不再额外敲代码了 直接使用定义的store里面的数据复制到两个module里面
const moduleL = {这里复制store里面的数据即可}
const moduleX = {这里复制store里面的数据即可}
// 将第一号的模块放入module(store的)中
modules: {
moduleL,
moduleX
}
// 组件中定义方法来触发
// 直接使用changeCount来进行测试 需要再之前的store和模块中的mutations的addCount增加一句 console.log('muduleL里面的addCount'),console.log('muduleX里面的addCount'),console.log('store里面的addCount')
...mapMutations({
changeCount: 'addCount',
changeAge: 'addAge'
})
// 利用button 触发事件 发现很神奇的一幕,打印结果如下所示
store里面的addCount
muduleL里面的addCount
muduleX里面的addCount
// 因此可以推断出会触发所有定义相同名称的mutations,因为Mutations和actions的触发是不区分模块的,因此不能使用相同的名称,否则都会触发。
// 解决办法 使用命名空间
// 在模块内添加:namespaced: true
// 添加命名空间(每个模块内)
namespaced: true,
// 这里再次去触发按钮,触发结果如下
store里面的addCount
// 只会触发store里面,命名空间生效了
// 接下来看如何触发每个模块中的mutations,我将他放入的mounted中,页面加载的时候即触发
this.$store.commit('moduleX/addCount', 10)// 即可触发moduleX模块内的addCount
// 使用辅助函数来触发,mapState来映射出数据
...mapState('moduleX', {
moduleXcount: state => state.count
})
// 辅助函数mapMutation来定义出响应的commit
...mapMutations('moduleX',
{
clickMX: 'addCount'
}
)
下面提供响应的完整的测试代码,抽离文件和常量化根据个人习惯进行设置
// 组件代码
<template>
<div>
<p>the count is {{count}}</p>
<p>the age is {{age}}</p>
<p>这个是ModuleX里面的count 初次渲染 {{moduleXa}}</p>
<p>这个是ModuleX里面的count {{moduleXcount}}</p>
<p v-for="(item, index) in getList" :key="index + 's'" >{{item}}</p>
<button @click='getState'>count</button>
<button @click='getAge'>age</button>
<button @click='changeCount(10)'>addCount</button>
<button @click='changeAge(10)'>addAge</button>
<button @click="zeroAge">age0</button>
<button @click="clickMX(15)">改变moduleX的count</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
data() {
return {
// count: 10,
// age: 0
myList: [],
moduleXa: 0
}
},
mounted() {
this.$store.commit('moduleX/addCount', 10)
this.moduleXa = this.$store.state.moduleX.count
console.log(this.moduleXa)
// console.log(this.$store)
// this.count = this.$store.state.count
// this.age = this.$store.state.age
},
methods: {
...mapMutations('moduleX',
{
clickMX: 'addCount'
}
),
getState () {
console.log(this.count)
},
getAge() {
console.log(this.age)
},
...mapMutations({
changeCount: 'addCount',
changeAge: 'addAge'
}),
// zeroAge() {
// this.$store.dispatch('resetAge')
// }
...mapActions({
zeroAge: 'resetAge'
})
// changeCount (add) {
// this.$store.commit('addCount', add)
// }
},
computed: {
...mapState(['count', 'age']),
...mapState('moduleX', {
moduleXcount: state => state.count
}),
getList() {
console.log(this.$store.getters.getList)
return this.$store.getters.getList
}
}
}
</script>
// store/index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
// import { ADD_COUNT, SUB_COUNT, ASYNCCOUNT } from './mutation_type'
Vue.use(Vuex)
const moduleL = {
// 添加命名空间
namespaced: true,
state: {
count: 0,
age: 18,
list: [55, 66, 77, 88, 87, 25]
},
mutations: {
addCount (state, upload) {
console.log('muduleL里面的addCount')
state.count += upload
},
addAge(state, upload) {
state.age += upload
},
zeroAge(state) {
state.age = 0
}
},
actions: {
resetAge (content) {
console.log('content', content)
setTimeout(() => {
content.commit('zeroAge')
}, 3000)
}
}
}
const moduleX = {
// 添加命名空间
namespaced: true,
state: {
count: 0,
age: 18,
list: [55, 66, 77, 88, 87, 25]
},
mutations: {
addCount (state, upload) {
console.log('muduleX里面的addCount')
state.count += upload
},
addAge(state, upload) {
state.age += upload
},
zeroAge(state) {
state.age = 0
}
},
actions: {
resetAge (content) {
console.log('content', content)
setTimeout(() => {
content.commit('zeroAge')
}, 3000)
}
}
}
export default new Vuex.Store({
state: {
count: 0,
age: 18,
list: [55, 66, 77, 88, 87, 25]
},
getters: {
getList(state) {
return state.list.filter(item => item > 75)
}
},
mutations: {
addCount (state, upload) {
console.log('store里面的addCount')
state.count += upload
},
addAge(state, upload) {
state.age += upload
},
zeroAge(state) {
state.age = 0
}
},
actions: {
resetAge (content) {
console.log('content', content)
setTimeout(() => {
content.commit('zeroAge')
}, 3000)
}
},
modules: {
moduleL,
moduleX
}
})
简易的抽离文件和常量化(方便定位错误),这个是以前测试使用,不是十分晚上的分离,仅供参考
// 组件代码
<template>
<div>
<p>this is count from store is{{this.$store.state.count}}</p>
<p>准备提交commit 来修改count的值</p>
<button @click='ADD_COUNT(5)'>提交mutation来修改count的值++</button>
<button @click='SUB_COUNT(5)'>提交mutation来修改count的值--</button>
<button @click="ASYNCCOUNT">异步提交mutation</button>
</div>
</template>
<script>
import { mapMutations, mapActions } from 'vuex'
import { ADD_COUNT, SUB_COUNT, ASYNCCOUNT } from '@/store/mutation_type'
export default {
mounted () {
console.log(this.$store)
},
// 计算属性的方式来提交mutation
computed: {
},
// 下面是直接用函数的方法来提交mutation
methods: {
// addCount (x) {
// this.$store.commit(ADD_COUNT, x)
// },
// subCount (x) {
// this.$store.commit(SUB_COUNT, x)
// },
// asyncCount () {
// this.$store.dispatch(ASYNCCOUNT)
...mapMutations([ADD_COUNT, SUB_COUNT]),
...mapActions([ASYNCCOUNT])
// }
}
}
</script>
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import { ADD_COUNT, SUB_COUNT, ASYNCCOUNT } from './mutation_type'
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
[ADD_COUNT] (state, x) {
state.count += x
},
[SUB_COUNT] (state, x) {
state.count -= x
},
[ASYNCCOUNT] (state) {
state.count = 0
}
},
actions: {
[ASYNCCOUNT] (content) {// 这里是个不完美的配置 没有单独的配置一个actions的常量文件
console.log(content)
setTimeout(() => { content.commit(ASYNCCOUNT) }, 5000)
}
},
modules: {
}
})
mutation_type.js文件
export const ADD_COUNT = 'ADD_COUNT'
export const SUB_COUNT = 'SUB_COUNT'
export const ASYNCCOUNT = 'ASYNCCOUNT'