五、vuex

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,详细看以上代码。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • Vuex 是什么? ** 官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式**。它采用集中...
    Rz______阅读 2,295评论 1 10
  • 一、Vuex是什么 Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有...
    寻找梦的猪猪阅读 260评论 0 0
  • Vuex[https://vuex.vuejs.org/zh/] 是一个专为 Vue.js 应用程序开发的状态管理...
    lio_zero阅读 473评论 1 6
  • 学习目的 了解和熟练使用 VueX,能够在实际项目中运用。 VueX介绍 Vuex 是一个专为 Vue.js ...
    _1633_阅读 2,782评论 0 7
  • 目录 Vue组件间通信方式回顾组件内的状态管理流程组件间通信方式父组件给子组件传值 (最简单的一种方式)子组件给父...
    顽皮的雪狐七七阅读 691评论 0 3