Vue组件之间State共享数据Vuex

58 篇文章 2 订阅

Vuex

1. 介绍

什么是Vuex

官网:https://vuex.vuejs.org/zh/

Vuex 是一个专为 Vue.js 应用程序开发的数据状态管理模式。

它采用集中式存储管理应用中所有组件的共享数据,Vuex是组件之间数据共享的一种机制。

在这里插入图片描述

2. 为什么要有Vuex

父子组件传值或兄弟组件传值,太麻烦了,不好管理。

vuex提供了一种全新的数据共享管理模式,该模式相比较简单的组件传值更加高端、大气、上档次。

注意

  1. 只有组件间共享的数据,才有必要存储到vuex中,组件自己私有的数据,还是要存储到自己的data中;
  2. 在应用的时候要因地制宜,普通组件传值 和 vuex 适合应用在不同场合,要注意区分。

3. 初始化vuex

步骤

  1. 安装vuex

    npm i vuex
    
  2. main.js做如下设置

    import Vue from 'vue'
    import App from './App.vue'
    // 使用Vuex
    // 1. 导入vuex模块
    import Vuex from 'vuex'
    
    // 2. Vue对Vuex进行注册
    //    之后在组件内部就可以使用vuex的相关成员了
    //    Vue.prototype.$store = xxx
    Vue.use(Vuex) // 插件应用
    
    // 3. 实例化vuex对象,并做具体配置
    //    new Vuex.Store() 是固定用法
    //    store:名字暂时是固定的,因为后续对其有使用
    const store = new Vuex.Store({
      // state:固定标志,给Vuex配置"共享数据",通过对象成员体现
      state: {
        // 具体数据,数据名称可以自定义,数量不限制
        count: 25,
        count1: 26
        // ……
      }
    })
    
    Vue.config.productionTip = false
    
    new Vue({
      // 4. 对vuex进行挂载
      store, // 简易成员赋值,store:store
      render: h => h(App)
    }).$mount('#app')
    

4. 访问vuex共享的数据

4.1. state

语法

this.$store.state.xxx   	// 组件内,xxx:代表共享数据的名称
$store.state.xxx 	        // 模板中,xxx:代表共享数据的名称

应用

给First.vue设置如下代码:

<template>
    <div id="first">
      <p>我是大哥组件</p>
      <p>count的值为:{{$store.state.count}}</p>
    </div>
</template>

注意

  1. vuex数据既可以在模板中被访问,语法 $store.state.xxx
  2. 也可以在组件实例内部被访问,语法 this.$store.state.xxx

4.2. mapState

组件中的Vuex数据如果需要频繁被访问,那么类似这样的代码 this.$store.state.xxx 或 $store.state.xxx 需要被重复编写,显然,这个代码有点过于复杂,会增加很多工作量,有没有简便的方式处理呢?

可以使用mapState方式访问state成员

使用步骤

  1. 在应用组件里边按需导入 mapState 辅助函数:

    import { mapState } from "vuex";
    
  2. 定义计算属性:

    computed: {
    	// 通过展开运算符,把state中的数据映射为计算属性
      ...mapState([xx,yy,zz……])
    }
    
    // mapState函数本质为如下:
    function mapState(arr){
      return {
        arr[0]:function(){
          return this.$store.state.arr[0]
        },
        arr[1]:function(){
          return this.$store.state.arr[1]
        }
        ……
      }
    }
    
  3. 然后在组件中就可以像访问data一样访问Vuex成员了。

使用示例

在Second.vue组件中通过mapState方式设置并访问共享数据:

<template>
    <div id="second">
      <p>我是小弟组件</p>
      <p>count的值为:
        <!--类似访问普通data成员一样,访问vuex数据-->
        {{count}}
        {{count1}}
      </p>
    </div>
</template>

<script>
// 通过mapState对共享数据做简化获取处理
import { mapState } from 'vuex'
export default {
  name: 'second',
  // 计算属性
  computed: {
    // 处理mapState,三个点是做展开运算的,运算结果与后边的内容是一致的
    ...mapState(['count', 'count1'])
    // 通过mapState对下述成员做简化处理
    // ...mapState(['count']) 是做展开操作,获得类似如下的函数
    // count: function () {
    //   return this.$store.state.count
    // },
    // count1: function () {
    //   return this.$store.state.count1
    // }
  }
}
</script>

注意

  1. 如果有多个成员都要经过mapState配置,可以这样...mapState([xx,yy,zz])
  2. mapState是把state共享数据配置为computed计算属性的成员。

5. 修改(同步)state共享数据

同步修改store中state上的值,需要借助mutations。通过mutations对state共享数据进行修改。

5.1. mutations

语法

// 在实例化Vuex对象的参数对象中,定义mutations成员(与state平级)对象
mutations:{
  // 参数state是固定的,代表vuex本身的state(名称可以自定义,为了可读性就用state即可),
  // 可以用以获取其中的共享数据
  // 第二个参数可以接收应用层参数信息
	方法名称: function(state,形参){
	    // 通过state修改内部的数据
        state.xx = 形参
	}
}

调用 mutations

// 组件实例调用
this.$store.commit('mutations方法名')
this.$store.commit('mutations方法名',实参)
// 模板中调用
$store.commit('mutations方法名')  
$store.commit('mutations方法名',实参)

使用示例

  1. 给vuex声明mutations和相关成员

    // mutations:固定标志,对共享数据做同步修改操作
    mutations: {
      // 声明修改数据的各个方法
      // mod是自定义名称
      // 参数state,可以自定义,但是就用state,可读性好,意思固定,就代表内部state对象成员(但是它们不是同一个对象)
      // 参数data,是自定义的,可以接收应用层的数据信息
      mod: function (state, data) {
        // 对共享数据最修改
        state.count += data
      }
    }
    
  2. 在First.vue中调用mutations成员

    <template>
      <div id="first">
        <p>我是大哥组件</p>
        <p>count的值为:{{$store.state.count}}</p>
        <p>
          <button @click="$store.commit('mod', 10)">修改count</button>
        </p>
      </div>
    </template>
    

注意

  1. 在组件实例内部可以通过this调用,例如 this.$store.commit('mod',10)
  2. 调用一次或多次都可以。
  3. 不要对this.$store.state.xxx 直接修改,容易造成数据混乱,因为许多组件都可以这样干。

5.2. mapMutations

组件中的Vuex数据如果需要频繁被修改,那么类似这样的代码 this.$store.commit(xx,yy) 需要被重复编写,显然,这个代码有点过于复杂,会增加很多工作量,有没有简便的方式处理呢?

可以使用mapMutations

使用步骤

  1. 在应用组件中做mapMutations 的模块化导入操作:

    import { mapMutations } from "vuex";
    
  2. 在methods方法中做如下设置:

    methods: {
      ...mapMutations([xx,yy,zz……])
    }
    
    // mapMutations 函数本质为如下:
    function mapMutations(arr){
      return {
        arr[0]:function(arg){
          return this.$store.commit(arg)
        },
        arr[1]:function(arg){
          return this.$store.commit(arg)
        }
        ……
      }
    }
    

注意

  1. mapState 是在computed中做展开,mapMutations是在methods中做展开。

  2. xx/yy/zz 是mutations成员名称,一个或多个都可以。

  3. 现在可以像访问methods方法一样直接访问mutations成员。

应用示例

在Second.vue中做如下配置:

<template>
  <div id="second">
    <p>我是小弟组件</p>
    <p>
      count的值为:
      <!--类似访问普通data成员一样,访问vuex数据-->
      {{count}}
      {{count1}}
    </p>
    <p>
      <!-- 如下代码冗余度很高 -->
      <!-- <button @click="$store.commit('mod', 10)">修改count</button>
      <!-- 用简便方式实现数据修改mapMutations,让mutations方法转变为methods方法-->
      <button @click="mod(10)">修改count</button>
    </p>
  </div>
</template>

<script>
// 通过mapState对共享数据做简化获取处理
import { mapState, mapMutations } from 'vuex'
export default {
  name: 'second',
  // 计算属性
  computed: {
    // 处理mapState,三个点是做展开运算的,运算结果与后边的内容是一致的
    ...mapState(['count', 'count1'])
    // 通过mapState对下述成员做简化处理
    // count: function () {
    //   return this.$store.state.count
    // },
    // count1: function () {
    //   return this.$store.state.count1
    // }
  },
  methods: {
    // 应用mapMutations
    ...mapMutations(['mod'])
    // 最终要通过 mapMutations 获得如下相关的方法
    // ...mapMutations(['mod']) 做展开操作,获得类似如下的函数
    // mod (arg) {
    //  return this.$store.commit('mod', arg)
    // }
  }
}
</script>

6. 修改(异步)state共享数据

mutations 和 actions 两个项目都是对Vuex的共享数据做修改的,它们的区别是:

  • mutations用在同步数据修改操作上
  • actions用在异步数据修改操作上

什么地方有异步操作:

  1. ajax/axios
  2. setTimeout
  3. fs.readFile()
  4. ……

6.1. actions

通过actions实现异步方式修改vuex的数据信息

声明语法

// actions:固定标志,对共享数据做异步修改
actions: {
  // 声明修改数据的成员方法,数量不限制
  // 参数context:可以自定义,但是就用context(官方就用之),是一个对象,
  // 具体代表$store(它们不是同一个对象)
  // 参数data:可以自定义名称,用于可以接收应用层的数据信息
  成员名称: function (context, data) {
    // actions规定要通过调用mutations成员修改数据(vuex内部规定的)
    context.commit(mutations成员,实参)
  }
}

调用语法

this.$store.dispatch('xx',参数)  // 组件内部,xx:代表actions内部成员名称
$store.dispatch('xx',参数)       // 模板,xx:代表actions内部成员名称

使用示例

  1. 在vuex中通过actions声明成员,实现异步修改数据操作

    actions: {
        xiu: function (context, data) {
          // 通过setTimeout实现“异步”请求,定时1s后执行
          setTimeout(() => {
            context.commit('mod', data)
          }, 1000)
        }
    }
    // 请求过来后停顿1秒后再操作,体现异步
    
  2. First.vue中调用actions方法

    <p>
        <button @click="$store.dispatch('xiu',10)">异步修改count</button>
    </p>
    

注意

  1. actions成员内部既可以操作mutations成员,也可以操作state成员。
  2. 一般不要操作 state,所有数据修改都通过mutations进行,尽管这样有点繁琐,但是好处是数据管理比较集中、专业,体现了只有mutations才拥有修改数据的特权。

6.2. mapActions

组件中的Vuex数据需要频繁被修改,那么类似这样的代码 this.$store.dispatch(xxx) 需要被重复编写,显然,这个代码有点过于复杂,会增加很多工作量,有没有简便的方式处理呢?

可以使用mapActions。

使用步骤

  1. 在应用组件中做mapActions 的模块化导入操作

    import { mapActions } from "vuex";
    
  2. 在methods方法中做如下设置

    methods: {
    	...mapActions([xx,yy,zz])
    }
    
    // mapActions 函数本质为如下:
    function mapActions(arr){
      return {
        arr[0]:function(arg){
          return this.$store.dispatch(arg)
        },
        arr[1]:function(arg){
          return this.$store.dispatch(arg)
        }
        ……
      }
    }
    

注意

  1. mapActions是在methods中做展开,xx/yy/zz 是actions成员名称,一个或多个都可以。
  2. 现在可以像访问methods方法一样访问actions成员了。

应用示例

Second.vue中设置如下代码:

<template>
  <div id="second">
    <p>我是小弟组件</p>
    <p>
      count的值为:
      <!--类似访问普通data成员一样,访问vuex数据-->
      {{count}}
      {{count1}}
    </p>
    <p>
      <!-- 如下代码冗余度很高 -->
      <!-- <button @click="$store.commit('mod', 10)">修改count</button>
	  <!-- 用简便方式实现数据修改mapMutations,让mutations方法转变为methods方法-->
      <button @click="mod(10)">修改count</button>
    </p>
    <p>
      <!-- <button @click="$store.dispatch('xiu',10)">修改(异步)count</button> -->
      <!-- 异步方式修改数据,用简便方式实现,像调用methods方法一样,去调用actions成员 -->
      <button @click="xiu(10)">修改(异步)count</button>
    </p>
  </div>
</template>

<script>
// 通过mapState对共享数据做简化获取处理
import { mapState, mapMutations, mapActions } from 'vuex'
export default {
  name: 'second',
  // 计算属性
  computed: {
    // 处理mapState,三个点是做展开运算的,运算结果与后边的内容是一致的
    ...mapState(['count', 'count1'])
    // 通过mapState对下述成员做简化处理
    // count: function () {
    //   return this.$store.state.count
    // },
    // count1: function () {
    //   return this.$store.state.count1
    // }
  },
  methods: {
    // 应用mapMutations
    ...mapMutations(['mod']),
    // 最终要通过 mapMutations 获得如下相关的方法
    // mod (arg) {
    //   this.$store.commit('mod', arg)
    // }

    // actions成员越多,越能体现mapActions的优势
    ...mapActions(['xiu'])
    // 上述语句会生成下述函数
    // xiu (arg) {
    //   执行动作不需要return
    //   要获得返回值才需要return
    //   this.$store.dispatch('xiu', arg)
    // }
  }
}
</script>

注意

​ mutations也可以实现异步方式操作数据,为什么不这样做呢?

  1. devtools调试工具有延迟,造成调试有误差。
  2. 比较混乱,不成规矩。
  3. Vuex倡导者也不推荐这样干。

在这里插入图片描述

上图来自官网,说明的事情有如下:

  1. Actions拥有与后端接口直接交互的特权,一般都是异步操作。
  2. Actions对mutations进行调用,调用 commit。
  3. mutations的操作可以直观反映在devtools调试工具中,方便程序调试。
  4. mutations对state进行直接操作。
  5. state状态数据可以渲染给组件显示。
  6. 组件实例通过 dispatch 调用actions。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值