一、Vuex介绍
1.Vuex是什么?
1.是一个专为 Vue.js 应用程序开发的状态管理模式
2.集中式存储管理应用的所有组件的状态
3.Vuex 也集成到 Vue 的官方调试工具 devtools extension
2.什么情况下我应该使用 Vuex?
1.如果应用够简单,最好不要使用 Vuex,一个简单的 store模式 就足够了
2.如果需要构建一个中大型单页应用,很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
二、Vuex安装
npm
npm install vuex --save
三、应用
1.最简单的 Store
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0,
token: ''
},
mutations: {
increment(state) {
state.count++
}
},
actions: {
incrementAsync(context) {
setTimeout(() => {
context.commit('increment');
}, 1000);
}
}
})
通过 store.commit 方法触发状态变更
通过 store.dispatch 方法异步触发状态变更
通过 store.state 来获取状态对象
store.commit('increment');
store.dispatch('incrementAsync');
console.log(store.state.count);
2.在 Vue 组件中操作 Vuex 状态
1.创建store.js模块,注册state、mutations、actions、getters
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
count: 0,
todos: [{ id: 1, text: 'abc', done: true }, { id: 2, text: 'def', done: false }]
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
incrementAsync(context, flag) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (flag) {
context.commit('increment');
resolve('成功');
} else {
reject('失败');
}
}, 1000);
});
}
},
getters: {
doneTodos(state, getters) {
return state.todos.filter(todo => todo.done);
},
doneTodosCount(state, getters) {
return getters.doneTodos.length;
},
getDoneById(state) {
return id => state.todos.find(todo => todo.id === id);
},
getTodosLength(state) {
return state.todos.length;
}
}
});
export default store;
2.注册到根组件
main.js
import Vue from 'vue';
import App from './App.vue';
import store from './store';
Vue.config.productionTip = false;
new Vue({
store,
render: h => h(App)
}).$mount('#app');
App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png" />
<HelloWorld msg="Welcome to Your Vue.js App" />
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue';
export default {
name: 'app',
components: {
HelloWorld
}
};
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
3.在子组件中使用
HelloWorld.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<div>
计数器{{count}}
<button @click="$store.commit('increment')">使用mutations增加计数</button>
<button @click="$store.dispatch('incrementAsync', true)">使用actions增加计数</button>
<button @click="incrementAsync(true)">使用actions增加计数</button>
</div>
<ul>
<li v-for="(doneTodo, index) in doneTodos" :key="index">{{doneTodo.text}}</li>
<li>doneCount共计: {{doneCount}}</li>
<li>数组共计长度: {{getTodosLength}}</li>
</ul>
<p>{{$store.getters.getDoneById(2)}}</p>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex';
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
localCount: 3
};
},
computed: {
doneTodos() {
return this.$store.getters.doneTodos;
},
// ...mapState({
// count: state => state.count,
// countAlias: 'count',
// // 为了能够使用 `this` 获取局部状态,必须使用常规函数
// countPlusLocalState(state) {
// debugger;
// return state.count + this.localCount;
// }
// })
...mapState(['count']),
...mapGetters({
// 把 `this.doneCount` 映射为 `this.$store.getters.doneTodosCount`
doneCount: 'doneTodosCount'
}),
...mapGetters(['getTodosLength'])
},
methods: {
...mapActions(['incrementAsync'])
}
};
</script>
四、注意点
1.不要直接修改state,必须通过mutations修改
2.有异步调用的情况下,必须通过actions修改
五、大型应用项目结构及Vuex分割模块示例:
├── public
│ └── index.html
├── src
│ ├── assets
│ ├── components
│ │ └── HelloWorld.vue
│ └── store
│ ├── index.js # 我们组装模块并导出 store 的地方
│ ├── actions.js # 根级别的 action
│ ├── mutations.js # 根级别的 mutation
│ └── modules
│ ├── cart.js # 购物车模块
│ └── products.js # 产品模块
├── App.vue
└── main.js
六、个人对vuex与vue的一些设计共性理解
属性 | 描述 |
---|---|
state | 相当于vue中的data |
mutations | 相当于vue中的methods,而且必须为同步函数, 官方建议常量命名 |
actions | 作用是处理异步后再提交mutations |
getters | 相当于vue中的computed |
Vuex官方文档:https://vuex.vuejs.org/zh/