vuex入门
1.简介
vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件状态,并以相应的规则保证状态以一种可测的方式发生变化。
简单来说,用来集中管理数据,类似与React中的Redux,都是基于Flux的前端状态管理框架
2.基本用法
初始化项目vuex-demo
vue init webpack-simple vuex-demo
2.1 安装vuex
npm install vuex -S
2.2 创建store.js文件,在main.js中导入并配置store选项
main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store.js'
new Vue({
store, //配置store选项,指定为store对象,vue会自动把store对象建到所有子组件中,在子组件中通过this.$store访问该store对象
el: '#app',
render: h => h(App)
})
2.3 编辑store.js文件
Vuex的核心是store(仓库),相当于一个容器,一个store实例中包含以下属性的方法:
state 定义属性(状态,数据)
getters 用来获取属性
actions 定义方法(动作)
commit 提交变化,修改数据的唯一方式就是显式的提交mutations
mutations 定义变化
注意:不能直接在actions中直接修改数据,数据修改必须在mutations
store.js
/*
vuex配置
*/
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
//定义属性(数据)
var state = {
count:6
}
//定义getters
var getters = {
count(state){
return state.count;
},
evenOrodd(state){
return state.count%2==0?'偶数':'奇数';
}
}
//定义actions,要执行的操作,如流程判断,异步请求
const actions = {
increment(context){ //参数context本身也是一个对象:包含commit、dispatch、state
// console.log(context);
context.commit('increment'); //提交一个名为increment的变化,名称可以自定义,可以认为是类型名
},
//es6写法
/*
increment({commit,state}){
commit('increment'); //提交一个名为increment的变化,名称可以自定义,可以认为是类型名
},
*/
decrement(context){
if(context.state.count > 10){
context.commit('decrement');
}
},
incrementAsync({commit,state}){
//es6写法
/*
var p = new Promise((resolve,reject) => {
setTimeout(() => {
resolve();
},3000);
});
p.then(() => {
commit('incrementAsync');
}).catch(() => {
console.log('异步失败');
});
*/
new Promise(function(resolve,reject){
setTimeout(function(){
resolve();
},3000);
}).then(function(){
commit('increment');
}).catch(function(){
console.log('异步失败');
});
}
}
//定义mutations,处理状态(数据)的改变
const mutations = {
increment(state){
state.count++;
},
decrement(state){
state.count--;
}
}
//创建store对象
const store = new Vuex.Store({
state,
getters,
actions,
mutations
})
//导出store对象
export default store;
2.4 编辑App.vue访问
在子组件中访问store对象的俩种方式:
+ 方式1:通过this.$store访问
+ 方式2:通过mapState、mapGetters、mapActions访问,vue提供了俩个方法
mapGetters 获取属性(数据)
mapActions 获取方法(动作)
App.vue
<template>
<div id="app">
<button @click="increment">增加</button>
<button @click="decrement">减少</button>
<button @click="incrementAsync">异步增加</button>
<p>当前数字为:{{count}}</p>
<p>当前数字为:{{evenOrodd}}</p>
</div>
</template>
<script>
import {mapState,mapGetters,mapActions} from 'vuex'
export default {
name: 'app',
data() {
return {
msg: 'Welcome to Your Vue.js App'
}
},
//方式1:通过this.$store访问
/*
computed:{
count(){
return this.$store.state.count;
}
}
*/
//方式2
/*
computed:mapState([
'count'
]),
*/
// 方式3:通过mapGetters、mapActions访问
computed:mapGetters([
'count',
'evenOrodd'
]),
methods:mapActions([
'increment',
'decrement',
'incrementAsync'
])
}
</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.更好的组织vuex项目结构
|-src
|-store
|-index.js //我们组装模块并导出 store 的地方
|-getters.js //根级别的 getter
|-actions.js //根级别的 action
|-mutations.js //根级别的 mutation
|-mutationtypes.js //定义mutation
|-modules //分为多个模块,每个模块都有自己的state、getters、actions、mutations
|-user.js //用户模块
|-cart.js //购物车模块
|-goods.js /产品模块
|.....
index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
import getters from './getters.js'
import actions from './actions.js'
import user from './modules/user.js'
export default new Vuex.Store({
getters,
actions,
modules:{
user
}
});
getters.js
const getters = {
evenOrodd(state){
return state.user.count%2==0?'偶数':'奇数';
}
}
export default getters;
actions.js
import mutationtypes from './mutationtypes.js'
const actions = {
incrementAsync({ commit, state }) {
new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, 3000);
}).then(() => {
commit(mutationtypes.INCREMENT)
}).catch(() => {
console.log('异步操作失败');
});
}
}
export default actions;
mutationtypes.js
/*
定义类型常量
*/
const INCREMENT = 'INCREMENT'
const DECREMENT = 'DECREMENT'
export default {
INCREMENT,
DECREMENT
}
user.js
/*
用户数据
*/
import mutationtypes from '../mutationtypes.js' //一般把mutation行为定义成常量的形式,一起放在mutationtypes.js中
const state = {
count:12
}
var getters = {
count(state){
return state.count;
}
}
const actions = {
increment({commit,state}){
// commit('increment'); //一般把mutation行为定义成常量的形式,一起放在mutationtypes.js中
commit(mutationtypes.INCREMENT);
},
decrement({commit,state}){
if(state.count > 10){
// commit('decrement');
commit(mutationtypes.DECREMENT);
}
}
}
const mutations = {
// increment(state){
// mutationtypes.DECREMENT(state){ //mutationtypes.DECREMENT是变量
[mutationtypes.INCREMENT](state){ //ES6中[]将变量转化为字符串
state.count++;
},
[mutationtypes.DECREMENT](state){
state.count--;
}
}
export default {
state,
getters,
actions,
mutations
}
main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store/index.js'
new Vue({
store,
el: '#app',
render: h => h(App)
})
App.vue
<template>
<div id="app">
<button @click="increment">增加</button>
<button @click="decrement">减少</button>
<button @click="incrementAsync">异步增加</button>
<p>当前数字为:{{count}}</p>
<p>当前数字为:{{evenOrodd}}</p>
</div>
</template>
<script>
import {mapState,mapGetters,mapActions} from 'vuex'
export default {
name: 'app',
data() {
return {
msg: 'Welcome to Your Vue.js App'
}
},
//方式1:通过this.$store访问
/*
computed:{
count(){
return this.$store.state.count;
}
}
*/
//方式2
/*
computed:mapState([
'count'
]),
*/
// 方式3:通过mapGetters、mapActions访问
computed:mapGetters([
'count',
'evenOrodd'
]),
methods:mapActions([
'increment',
'decrement',
'incrementAsync'
])
}
</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>