vuex 渐进式教程,从入门级带你慢慢深入使用vuex。
安装
安装vue-cli:
1.cnpm install -g vue-cli
2. vue init webpack vuex
安装vuex
cnpm i vuex --save
1.初级使用方法
// main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import Vuex from 'vuex' // 引入vuex
Vue.config.productionTip = false
Vue.use(Vuex);
let store = new Vuex.Store({ // store 对象
state:{
count:0
}
})
/* eslint-disable no-new */
new Vue({
el: '#app',
router,
store, //使用store,这可以把 store 的实例注入所有的子组件
components: { App },
template: '<App/>'
})
此时可以在组件中使用this.$store.state.count
获取store中state的值。如:
// 在组件的computed中使用
computed:{
count(){
return this.$store.state.count;
}
}
想想一下当项目比较大的时候数据繁琐,如果按照上述方法使用vuex,当你打开main.js你看的到场景是比较混乱的,各种数据繁杂在一起,不便于日后的维护。请看下一步:
2.中级使用方法: modules 模块化
state用法
2.1 在main.js中删除下述这部分代码
let store = new Vuex.Store({ // store 对象
state:{
count:0
}
})
2.2. 在src目录下新建store文件夹并在该文件夹下新建index.js文件。
在 store/index.js写入:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
strict:true, // 开启严格模式 确保state 中的数据只能 mutations 修改
state:{
count:0
}
})
export default store;
对应的main.js应该写入:
import store from './store'
写到这里,我们在组件里就可以获取到store里的state的值了
2.3 为了方便测试直接在HelloWorld.vue 中使用store
<template>
<div class="hello">
<h2>{{count}}</h2>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
computed:{
count(){
return this.$store.state.count;
}
}
}
</script>
很多时候咱们要对state里的值进行操作,在vuex提供了一个方法mutations
mutations用法(使用mutations可以修改state的值)
在sore\index.js写入:
//
...
state:{
count:0
},
mutations:{ // 更改数据的方法
add(state){
state.count++
},
//提交载荷用法
// add(state,n){
// state.count += n
// },
sub(state){
state.count--
}
}
...
//
组件(HelloWorld.vue)中使用mutations里对应的方法:
<template>
<div class="hello">
<button @click="add">+</button>
<h2>{{count}}</h2>
<button @click="sub">-</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
computed:{
count(){
return this.$store.state.count;
}
},
methods:{
add(){
this.$store.commit('add');
},
//提交载荷用法
// add(){
// this.$store.commit('add',10);
// },
//对象风格的提交方式
// store.commit({
// type: 'add',
// n: 10
// })
sub(){
this.$store.commit('sub');
}
}
}
</script>
此时就可以对count进行修改了。
当你想异步操作的时候,由于mutation必须是同步的这一点,此时不能采用mutation对state 进行修改。action派上用场了,action就是一个函数集合,在里面怎么操作都可以,只要最后触发mutation 就可以了。
现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。
Action 用法
在sore\index.js写入:
mutations:{ // 更改数据的方法
add(state){
state.count++
},
sub(state){
state.count--
}
},
++++
actions:{
add(context){ // context 与 store 实例具有相同方法和属性(但不是store 实例)
setTimeout(()=>{
context.commit('add');
},1000)
}
}
++++
组件(HelloWorld.vue)中使用getters里对应的方法:
<template>
<div class="hello">
<button @click="add">+</button>
++++
<button @click="add_action">action +</button>
++++
<h2>{{count}}</h2>
<button @click="sub">-</button>
<div>
test: {{doneTodos[0].text}} <br>
length: {{doneTodosLength}}
</div>
</div>
</template>
export default {
methods:{
add(){
this.$store.commit('add');
// console.log(this);
},
sub(){
this.$store.commit('sub');
},
++++
add_action(){
this.$store.dispatch('add');
}
++++
}
}
看到这里有没有想过当我们使用state中某一个数据时,我们只想用该数据中符合条件的数据。比如:
state:{
count:0,
todos: [
{ id: 1, text: 'text1--true', done: true },
{ id: 2, text: 'text2--false', done: false }
]
}
此时我们只想获取state.todos中done为true的数据时我们应该怎么获取?
可能会有以下两种方案:
1.每个在组件中首先获取todos,然后使用filter方法过滤;
2.写一个公共函数在每个组件中调用以下;
如果用到todos中done为true的组件很多,这两种方法都是很不理想的。Vuex为此为我们引入了一个方法Getter。
Getter 用法
在sore\index.js写入:
mutations:{ // 更改数据的方法
add(state){
state.count++
},
sub(state){
state.count--
}
},
+++
getters:{ // 用法类似组件中的 computed, 可以认为是store的计算属性
doneTodos:state => { // Getter 接受 state 作为其第一个参数:
return state.todos.filter(todo => todo.done) // -> [{ id: 1, text: 'text1--true', done: true }]
},
// Getter 也可以接受其他 getter 作为第二个参数
doneTodosLength:(state,getters) => {
return getters.doneTodos.length // -> 1
},
+++
}
组件(HelloWorld.vue)中使用getters里对应的方法:
<template>
<div class="hello">
<button @click="add">+</button>
<h2>{{count}}</h2>
<button @click="sub">-</button>
+++
<div>
test: {{doneTodos[0].text}} <br>
length: {{doneTodosLength}}
</div>
+++
</div>
</template>
<script>
export default {
//...
computed:{
+++
doneTodos(){
return this.$store.getters.doneTodos // -> [{ id: 1, text: 'text1--true', done: true }]
},
doneTodosLength(){
return this.$store.getters.doneTodosLength // -> 1
}
+++
}
}
</script>