关于Vuex是什么就不花大的篇幅来解释了,可以简单理解成全局的 data
,若您完全没有使用过vuex,建议先看看官方文档中对于Vuex的描述再来看本篇。关于Vuex的使用有以下需要注意的点👇
在store的index.js文件中定义一个name
:
import { createStore } from 'vuex'
export default createStore({
state: {
name: 'Jae'
},
mutations: {
},
actions: {
},
modules: {
}
})
在页面中使用它:
<template>
<div class="about">
<h1>This is an about page</h1>
<h2>{{ myName }}</h2>
</div>
</template>
<script>
export default {
computed: {
myName() {
return this.$store.state.name
}
}
}
</script>
效果如下👇
现在我想要实现一个功能,点击h1标题之后将name
中的“Jae”修改成“Jack”,怎么做?有人可能会理所当然地想到:
<template>
<div class="about">
<h1 @click="handleClick">This is an about page</h1>
<h2>{{ myName }}</h2>
</div>
</template>
<script>
export default {
computed: {
myName() {
return this.$store.state.name
}
},
methods: {
handleClick() {
this.$store.state.name = 'Jack'
}
},
}
</script>
在页面上自己试试其实效果也是正确的,但是官方并不推荐这么做。而且当你在初始化store的时候如果加上了严格模式,无论何时发生了状态变更且不是由 mutation
函数引起的,将会抛出错误。正确写法是:
<template>
<div class="about">
<h1 @click="handleClick">This is an about page</h1>
<h2>{{ myName }}</h2>
</div>
</template>
<script>
export default {
computed: {
myName() {
return this.$store.state.name
}
},
methods: {
handleClick() {
// 第一步,使用dispatch方法,派发一个action,名字叫change
this.$store.dispatch('change')
// 没有用到异步的话上面写成this.$store.commit('change')就可以了,不需要多派发一个action
}
},
}
</script>
import { createStore } from 'vuex'
export default createStore({
state: {
name: 'Jae'
},
// 约定俗成mutation里面只允许写同步代码,不允许异步代码
mutations: {
// 第四步,mutation感知到提交的change改变,执行change方法
change() {
// 第五步,在mutation中修改数据
this.state.name = 'Jack'
}
},
// 涉及到异步操作的话放到actions中
actions: {
// 第二步,store感知到你触发了一个叫做change的action,执行change方法
change() {
// 第三步,commit一个叫做change的改变,触发mutation
this.commit('change')
}
},
modules: {
}
})
归纳一下:
- 为什么vuex中要通过
mutations
修改state,而不是直接修改state?
因为state是实时更新的,mutations无法进行异步操作,而如果直接修改state的话是能够异步操作的,当你异步对state进行操作时,还没执行完,这时候如果state已经在其他地方被修改了,这样就会导致程序存在问题了。所以state要同步操作,通过mutations的方式限制了不允许异步。
当然了,一个最直白的原因。不统一在mutations中修改数据的话,你在各个页面直接修改state,后期怎么维护呢?
- 约定俗成mutation里面只允许写同步代码,不允许异步代码
- 涉及到异步操作的话放到actions中
- 没有用到异步的话
this.$store.commit('change')
就可以了,不需要多派发一个action - dispatch 和 actions 做关联
- commit 和 mutations 做关联
- 具体操作步骤与注意事项上方代码中注释已注明
拓展:
事件中触发 this.$store.dispatch('change')
可以携带参数,例如 this.$store.dispatch('change', 'Jack')
。需要注意的是 actions
中的change和mutations
中的change第二个参数才是dispatch传过来的参数👇
mutations: {
// 注意,mutations 中 change 第一个参数是state
change(state, str) {
state.name = str
}
},
actions: {
// 注意,actions 中 change 第一个参数是store
change(store, str) {
store.commit('change', str)
}
}