1、VueX的介绍与作用解析
VueX:是一个专门为vue.js应用程序开发的状态管理模式
1)、它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
2)、VueX也集成了Vue的官方调试工具 devtools extension,提供了诸如零配置的time-travel 调试、状态快照导入导出等高级调试功能。
状态管理是什么?
状态管理模式、集中式存储管理这些名字有点高大上,让人找摸不透。其实你可以简单的将其看成把需要多个组件共享的变量全部存储到一个对象里面;然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用;
应用场景:
用户的登录状态、用户名称、用户头像等
1.1、vux 单界面到多界面状态管理切换
安装Vuex命令:
npm install vuex --save
示例代码如下:
1)、配置vuex,一般会新建一个文件夹,独立管理vuex配置:新建文件夹 store/index.js
import Vue from 'vue';
import Vuex from 'vuex'
//安装插件
Vue.use(Vuex);
//创建对象
const store = new Vuex.Store({
state :{
num:0
},
mutations:{
//方法
addition(state){
state.num++;
},
subtract(state){
state.num--;
}
},
actions:{},
getters:{},
modules:{}
});
//导出
export default store;
2)、在main.js中进行挂载
import store from "./store";
new Vue({
el: '#app',
store,
render: h => h(App)
})
3)、新建组件 Index.vue
<template>
<div>
<span> {{ this.$store.state.num }}</span><br>
<button @click="Add">+</button>
<button @click="Subtract">-</button>
</div>
</template>
<script>
export default {
name: "Index",
methods:{
Add(){
this.$store.state.num++;
},
Subtract(){
this.$store.state.num--;
}
}
}
</script>
<style scoped>
</style>
4)、新建组件 Info.vue ,代码如下:
<template>
<div>
<span>{{ this.$store.state.num }}</span><br>
</div>
</template>
<script>
export default {
name: "Info"
}
</script>
<style scoped>
</style>
5)、在App.vue 中挂载两个组件,代码如下:
<template>
<div id="app">
<Index/>
<Info/>
</div>
</template>
<script>
import Index from './components/Index'
import Info from "./components/Info";
export default {
name: 'App',
components: {
Index,
Info
}
}
</script>
<style>
</style>
总结:
vuex 的安装、配置以及使用状态。
如果修改状态值,以上的代码是可以使用的,但是官方是不建议这样使用,因为这样使用是无法监听是谁修改的这个状态。
修改状态值是在 mutations 进行修改状态的值,这样就可以监听是谁修改的值,具体使用方法看实例代码。
1.2、Vuex-state 单一状态树的理解:
state:状态值 单一状态树
单一状态树:单一数据源
mutations:修改状态值
action:进行一些异步操作
getters:类似于组件中的计算属性
getters的使用实例:
import Vue from 'vue';
import Vuex from 'vuex'
//安装插件
Vue.use(Vuex);
//创建对象
const store = new Vuex.Store({
state :{
num:0
},
mutations:{
//方法
addition(state){
state.num++;
},
subtract(state){
state.num--;
}
},
actions:{},
//getters的使用
getters:{
multiply(state){
return state.num*2;
}
},
modules:{}
});
//导出
export default store;
vue调用方法:
{{this.$store.getters.multiply}}
modules :划分模块,根据不同的模块进行一系列的操作
mutations的使用
更新状态唯一的方式就是 提交 mutations 。
mutations 主要包括两部分:
①、字符串类型事件
②、一个回调函数,该毁掉函数的第一个参数是state
1)、示例代码: store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
//安装组件
Vue.use(Vuex);
//创建对象
const store = new Vuex.Store({
state: {
num: 0
},
mutations: {
Add(state) {
state.num++;
},
Cut(state) {
state.num--;
},
AddFive(state,payload){
console.log(payload)
//第一种接收
state.num = state.num + payload;
//第二种接收 第二个参数是一个对象
state.num = state.num + payload.num1;
}
}
});
//导出
export default store;
2)、组件中调用,示例代码:
//不传参
this.$store.commit('mutations方法名称');
//第一种传参
this.$store.commit('mutations方法名称',参数);
/第二种传参
this.$store.commit({type:'mutations方法名称',参数 });
总结: mutations中函数传参,第一个参数state是固定的 ,第二个参数是要传递的。
getters的使用:
getters的使用和组件中的计算属性差不多,示例代码如下:
import Vue from 'vue';
import Vuex from 'vuex';
//安装组件
Vue.use(Vuex);
//创建对象
const store = new Vuex.Store({
state: {
num: 0
},
getters:{
//不传参
numAddNum(state){
return state.num+state.num;
},
//传递 参数
numAddNumParms(state,getters){
return s =>{
return getters.numAddNum + s;
}
}
}
});
//导出
export default store;
在组件中调用,示例代码如下:
<!--不传参-->
<div>这是getters计算的值:{{this.$store.getters.numAddNum}}</div>
<!--传递参数-->
<div>这是getters传参计算的值:{{this.$store.getters.numAddNumParms(2)}}</div>
Mutation 的响应规则
响应规则:
①、提前store中初始化属性。
②、当给state 中的对象添加新属性时,使用下面的方式:
方式1:使用Vue.set(obj,'newProp',123)
方式2:用新对象给旧对象重新赋值
示例代码如下: store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
//安装组件
Vue.use(Vuex);
//创建对象
const store = new Vuex.Store({
state: {
student:[
{id:1,name:'xiaoming',sex:'男'},
{id:2,name:'xiaogang',sex:'女'}
]
},
mutations: {
AddProperty(state) {
console.log("添加对象属性");
Vue.set(state.student[0], 'adress', '12312');
}
}
});
//导出
export default store;
组件中调用,示例代码如下:
<div>这是student对象值:{{this.$store.state.student}}</div>
<button @click="AddProperty">添加student对象属性</button>
<script>
export default {
name:'Index',
methods:{
AddProperty(){
this.$store.commit('AddProperty');
}
}
}
</script>
mutation的类型常量
由于项目越来越大,mutation中的方法越来越多,为了更好的管理这些方法,可以将这些方法名单独抽出文件来进行管理。
①、 示例代码如下:新建 mutation-types/index.js
export const ADDPROPERTY = 'AddProperty'
②、在store/index.js文件中导入文件,示例代码:
import Vue from 'vue';
import Vuex from 'vuex';
import * as types from '../mutation_types'
//安装组件
Vue.use(Vuex);
//创建对象
const store = new Vuex.Store({
state: {
num: 0,
student:[
{id:1,name:'xiaoming',sex:'男'},
{id:2,name:'xiaogang',sex:'女'}
]
},
mutations: {
[types.ADDPROPERTY](state) {
console.log("添加对象属性");
Vue.set(state.student[0], 'adress', '12312');
}
}
});
//导出
export default store;
③、在组件中调用,示例代码如下:
<div>这是student对象值:{{this.$store.state.student}}</div>
<button @click="AddProperty">添加student对象属性</button>
<script>
import * as types from '../mutation_types'
export default {
name:'Index',
methods:{
AddProperty(){
this.$store.commit(types.ADDPROPERTY);
}
}
}
</script>
Vuex-Action 的基本使用
Action主要应用于异步,同步方法在Mutation中进行定义。
基本使用:在store/index.js 示例代码:
import Vue from 'vue';
import Vuex from 'vuex';
import * as types from '../mutation_types'
//安装组件
Vue.use(Vuex);
//创建对象
const store = new Vuex.Store({
state: {
num: 0,
student:[
{id:1,name:'xiaoming',sex:'男'},
{id:2,name:'xiaogang',sex:'女'}
]
},
mutations: {
[types.ADDPROPERTY](state) {
console.log("添加对象属性");
Vue.set(state.student[0], 'adress', '12312');
}
},
actions:{//用于一步操作
aUpdata(context){
setTimeout(() => {
console.log('执行异步操作');
//异步操作在Actions中进行,但是修改值必须经过mutation
context.commit(types.ADDPROPERTY);
}, 2000);
}
}
});
//导出
export default store;
在组建中调用,示例代码:
<div>这是student对象值:{{this.$store.state.student}}</div>
<button @click="AddPropertyAsync">异步操作添加student对象属性</button>
<script>
import * as types from '../mutation_types'
export default {
name:'Index',
methods:{
AddPropertyAsync(){
this.$store.dispatch('aUpdata');
}
}
}
</script>
总结:
异步操作必须在Actions中进行操作,但是修改的值必须经过Mutation。
Actions 与 Promise 结合使用,示例代码:
import Vue from 'vue';
import Vuex from 'vuex';
import * as types from '../mutation_types'
//安装组件
Vue.use(Vuex);
//创建对象
const store = new Vuex.Store({
state: {
num: 0,
student:[
{id:1,name:'xiaoming',sex:'男'},
{id:2,name:'xiaogang',sex:'女'}
]
},
mutations: {
[types.ADDPROPERTY](state) {
console.log("添加对象属性");
Vue.set(state.student[0], 'adress', '12312');
}
},
actions:{
aUpdata(context){
return new Promise((resolve, reject) => {
console.log('执行异步操作');
context.commit(types.ADDPROPERTY);
resolve('Ok');
});
}
}
});
//导出
export default store;
组件中调用,示例代码如下:
<div>这是student对象值:{{this.$store.state.student}}</div>
<button @click="AddPropertyAsync">异步操作添加student对象属性</button>
<script>
import * as types from '../mutation_types'
export default {
name:'Index',
methods:{
AddProperty(){
this.$store.commit(types.ADDPROPERTY);
},
AddPropertyAsync(){
this.$store.dispatch('aUpdata').then((res)=>{
console.log('执行成功');
console.log(res);
});
}
}
}
</script>
modules的基本使用:
Vue使用单一状态树,那么也意味着有很多状态都得需要交给Vuex来管理,当应用变的很复杂时,那么store对象会变得很臃肿,为了解决这个问题,vuex允许我们将store分割成很多模块,每个模块都有自己的 state actions getters mutations。
示例代码如下: store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
//安装
Vue.use(Vuex);
const TestModule = {
state: {
num: 0,
payload:0,
name:'小刚'
},
mutations: {
add(state) {
state.num++;
},
subtraction(state) {
state.num--;
},
parms(state,payload){
state.payload = payload;
}
},
getters:{
fullname(state){
return state.name = '李'+state.name;
},
fullname1(state,getters){
return getters.fullname+2222;
},
fullname2(state,getters,rootState){
return getters.fullname1+rootState.rootname;
}
},
actions:{
updateNameAsync(context){
setTimeout(()=>{
context.commit('parms',"再见");
context.commit('updaterootName');
context.rootGetters.test ('开发');
console.log(context);
},1000);
}
}
};
//创建对象并导出对象
export default new Vuex.Store({
state:{
rootname:'fuck'
},
mutations:{
updaterootName(state)
{
state.rootname = "you";
}
},
modules: {
TestModule
},
getters:{
test(state,getters)
{
return (s)=>{
return state.rootname = s;
}
}
}
});
组件中调用,示例代码如下:
<template>
<div class="hello">
<h2>TestModule 的 state状态值:{{this.$store.state.TestModule.num}}</h2>
<h2>TestModule 的 mutations 参数传值:{{this.$store.state.TestModule.payload}}</h2>
<h2>TestModule 的 getters无参值:{{this.$store.getters.fullname}}</h2>
<h2>TestModule 的 使用getters参数获取fullname函数在拼接值:{{this.$store.getters.fullname1}}</h2>
<h2>TestModule 的 使用rootgetters参数获取根getter中的函数在拼接值:{{this.$store.getters.fullname2}}</h2>
<div>
<button @click="add">+</button>
<button @click="subtraction">-</button>
<button @click="parms">Mutations 传值</button>
<button @click="updateAsync">异步修改</button>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
},
methods:{
add(){
this.$store.commit('add');
},
subtraction(){
this.$store.commit('subtraction')
},
parms(){
console.log(this.$store.commit('parms',4));
},
updateAsync(){
this.$store.dispatch('updateNameAsync');
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
总结:
getters中可以调用根中state对象 关键字:rootstate
actions中的context参数也可以调用根中的rootGetters、rootstate、mutations,详细看以上代码。