目录:
- 简介
- Vuex原理图
- 基本用法
一、简介
1.1、Vuex的概念和作用
Vuex 是一个专为 Vue.js 引用程序并发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式放生变化。简单来说:Vuex是用来集中管理数据,类似于React中的Redux(回来,回家),都是基于Flux(融化了)的前端状态管理框架。Vuex 一般小项目,写两个页面是用不到的,但是中大型项目是需要用到的。
1.2、访问Vuex官网方式
1.Vuex的官网:https://vuex.vuejs.org/zh/
2.也可以通过 Vue.js 官网进入 Vuex的官网:生态系统 -> 核心插件 -> Vuex
1.3、什么是组件状态?
比如说你的组件会有不同的状态,这个状态比如说显示或者隐藏,或者你的数据的需要展示,你的数据管理等等,都可以使用Vuex来操作。
1.4、Vuex在集中管理数据起到什么作用?
集中管理数据的,你的项目当中很多数据需要管理,包括你的组件间需要数据的传递,传递的方式我们也可以用不同的方式,如:父子组件的数据传递(props和触发事件),非父子组件的数据传递(中央总线方式)。但是如果说你的项目太复杂,以组件的方式传递数据,用这种方式特别费劲,而且很乱。项目真的变大了之后,这种单线传递太麻烦了,所以现在基本都用Vuex。但是你的项目很简单,没有必要使用Vuex。
二、Vuex的原理图
这个原理图在官网也有,只不过我说明了一下。官网管理图

原理图说明:
1. Vue组件上操作,会发出(dispatch)一个动作(actions) -> 2. 提交(commit) 改变(mutation)的数据 -> 3.突变或者说改变(mutate) 状态(state)中的数据 -> 4.改变之后,重新渲染(render)组件(Vue Components) ->5.组件就会更新,展示更新过后的数据。
三、基本使用
3.1、安装Vuex
>npm install vuex -S
3.2、目录结构
|-vuex-demo
|-node-modules
|-src
|-assets
|-App.vue
|-main.js
|-store.js //vuex的相关配置都在store.js中
|-.babelrc
|-...
|-webpack.config.js
3.3、创建store.js文件,在main.js中导入并且配置store对象
说明:Vuex的相关配置都在这个里面配置的
import Vue from 'vue'
import App from './App.vue'
import store from './store.js' //导入store对象
new Vue({
el: '#app',
render: h => h(App),
//配置store选项,指定为store对象,会自动将store对象注入到所有子组件中(Vue实例是根组件,其他的都是子组件),在子组件中通过this.$store访问store对象
store //(缩写) store:store,导入Vuex后就有store这么一个选项,store值就是你导入的store
});
注意了:Vue实例是根组件,Vue实例下注册的组件,都是vue根组件下的子组件。
3.4、编辑 store.js
Vuex的核心是store(仓库),相当于一个容器,一个store实例中包含以下属性方法:
state: 定义属性(状态、数据) getters: 用来获取属性 actions: 定义方法(动作) commit: 提交变化,修改数据的唯一方式就是现实的提交mutations mutations: 定义变化(或突变),来改变数据
注:不能直接修改数据,必须是显式提交变化,目的是为了追踪到状态的变化
store.js的内容(方式1:通过this.$store访问) :
/*
* Vuex 配置
* */
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
//1.定义属性(数据)
var state={
count:6
};
//2.创建store对象
const store = new Vuex.Store({
state //(缩写) state:state
});
//3.导出store对象
export default store;
store.js的内容(方式2:通过mapGetters、mapActions访问) :
/*
* Vuex 配置
* */
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
//1.定义属性(数据)
let state={
count:6
};
//2.定义getters
let getters = {
count(state){ //参数state就是上面的state
return state.count;
}
};
//3.定义actions,要执行的操作,如流程判断,一部请求等
const actions = {
/*increment(context){ //对应的increment的就是App.vue中绑定的事件
console.log(context);
}*/
increment({commit,state}){ //es6的语法
commit('increment'); //提交(commit)一个名为increment的变化,名称自定义,可以认为是类型名
}
};
//4.定义mutations处理状态(数据)的改变
const mutations = {
increment(state){ //increment函数名必须跟 actions中的commit是一样的
state.count++;
}
};
//5.创建store对象
const store = new Vuex.Store({
state, //(缩写) state:state
getters,
actions,
mutations
});
//6.导出store对象
export default store;
我们先来看看actions是中的context有哪些东西:
▼{getters: {…}, state: {…}, rootGetters: {…}, dispatch: ƒ, commit: ƒ, …}
▶dispatch: ƒ boundDispatch(type, payload)
▶commit: ƒ boundCommit(type, payload, options)
▶getters: {}
▶state: {__ob__: Observer}
▶rootGetters: {}
▶rootState: {__ob__: Observer}
▶__proto__: Object
很明显是一个对象,但是我们用es6的语法使用,不然用起来比较麻烦!!!
3.5、编辑App.vue
在子组件中访问store对象的两种方式:
方式1:通过this.$store访问
方式2:通过MapState、mapGetters、mapActions访问,Vuex提供了2个方法:
MapState:获取state mapGetters: 获取getters,获取属性(数据) mapActions: 获取actions,获取方法(动作)
App.vue编辑(方式1:通过this.$store访问)
<template>
<div id="app">
<!--获取计算属性count-->
<p>当前数据为:{{count}}</p>
</div>
</template>
<script>
export default {
name: 'app',
//方式1: 通过this.$store访问
computed:{
count(){
return this.$store.state.count;
}
}
}
</script>
App.vue编辑(通过mapGetters、mapActions访问)
<template>
<div id="app">
<!--触发事件-->
<button @click="increment">增加</button>
<!--获取数据-->
<p>当前数据为:{{count}}</p>
</div>
</template>
<script>
//先导入mapState(匹配state),mapGetters(匹配属性),mapActions(匹配方法)方法
import {mapState,mapGetters,mapActions} from 'vuex'
export default {
name: 'app',
//方式2:通过mapGetters、mapActions访问
//computed:mapGetters([
// 'count' //对应的store.js中的getters中的count()方法
//]),
computed:mapState([
'count' //对应就是state中的count
]),
methods:mapActions([
'increment' //匹配store.js中的actions中的increment方法
])
}
</script>
通过mapState或者mapGetters都可以获取count值,这个就要看你喜欢用什么了,只不过mapState是直接获取 state中的值,而mapGetters是通过定义方法获取,而且用getters,来获取处理过的数据不一定就是直接的count,例子下面代码练习有。
3.6、Vuex的练习所有代码
说明:main.js就直接引用上面的,其他的完整练习代码如下,这边特别注意的是:我们在调代码的时候 可以 配合 vue-devtools 配合使用,使用方法:1-1 基本用法-第一个vue程序
1、App.vue组件
<template>
<div id="app">
<button @click="increment">增加</button>
<button @click="decrement">减少</button>
<button @click="incrementAsync">增加</button>
<!--获取数据-->
<p>当前数据为:{{count}}</p>
<p>{{isEvenOrOdd}}</p>
</div>
</template>
<script>
import {mapState,mapGetters,mapActions} from 'vuex'
export default {
name: 'app',
//方式2:通过mapGetters、mapActions访问
computed:mapGetters([
'count', //对应的store.js中的getters中的count()方法
'isEvenOrOdd'
]),
// computed:mapState([
// 'count' //对应就是state中的count
// ]),
methods:mapActions([
'increment',
'decrement',
'incrementAsync'
])
}
</script>
<style>
</style>
2、store.js代码:
/*
* Vuex 配置
* */
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
//1.定义属性(数据)
let state={
count:6
};
//2.定义getters
let getters = {
count(state){ //参数state就是上面的state
return state.count;
},
isEvenOrOdd(state){ //getters,来获取处理过的数据不一定就是直接的count
return state.count%2 == 0?'偶数':'奇数';
}
};
//3.定义actions,要执行的操作,如流程判断,一部请求等
const actions = {
/*increment(context){ //对应的increment的就是App.vue中绑定的事件
console.log(context);
}*/
increment({commit,state}){ //es6的语法
commit('increment'); //提交(commit)一个名为increment的变化,名称自定义,可以认为是类型名
},
decrement({commit,state}){
//在提交条件这边做判断
if(state.count>10){
commit("decrement");
}
},
incrementAsync({commit,state}){
//异步操作
let p = new Promise((resolve,reject) => {
setTimeout(() => {
resolve();
},3000);
});
p.then(()=> {
commit('increment'); //状态改变可以是同一个操作
}).catch(() => {
console.log('异步操作');
});
}
};
//4.定义mutations处理状态(数据)的改变
const mutations = {
increment(state){ //increment函数名必须跟 actions中的commit是一样的
state.count++;
},
decrement(state){
state.count--;
}
};
//5.创建store对象
const store = new Vuex.Store({
state, //(缩写) state:state
getters,
actions,
mutations
});
//6.导出store对象
export default store;
实现界面如下:
当前数据为:6
偶数
