Vue的状态管理「Vuex」

前言

  本文假设读者已经了解vue的基础语法,能够使用vue编写出简单的页面

Vue 组件间的通信

为了更全面认知我们来回顾一下以下内容。在Vue组件的世界里,数据传递分三种情况:

  • 父组件给子组件传递数据, 使用 props 选项声明接收,可以是对象(带校验),也可以是数组.
  • 子组件给父组件传递数据, 使用 $emit() 方法触发事件携带参数,父组件使用$on监听获取. 还有一种办法是 使用语法糖 v-model,在父组件写法上感觉就像普通的一个双向数据绑定方案,不同的是写在组件上而不是写在input控件上.子组件上依旧使用$emit('input', 要传递的数据对象)
  • 非父子组件通信, 怎么办? 很慌? $dispatch()派发?, $broadcast 广播? 中央事物总线bus? 别急,还有个更好用的Vuex

  关于非父子组件的通信,也就是跨级组件和兄弟组件通信时,vue1.x中采用$dispatch$broadcast这两种办法,在vue2.x中已经被废弃。取而代之的就是采用中央事物总线bus的办法,步骤如下

  1. 创建一个空的vue实例busvar bus = new vue(),里面没有任何内容
  2. 定义一个全局的组件component-a,假设这个组件就是我们要的跨级组件。当该组件中有数据更新,需要通知源组件时,使用bus.$emit('自定义事件名', ‘要传递的参数对象’)触发
  3. 在2中提到的源组件我们假设就是app中,在mounted时使用bus.$on('emit发起的事件名', function(param){ }) 来监听并获取到数据param

Vuex 能解决什么

  理论上我们使用纯vue就能解决所有的组件通信问题。但这也只是“理论上”,在大型的单页面SPA项目中,因为数据状态相对复杂,我们希望有更方便,更容易理解的办法操作和管理非父子组件的通信数据,更容易维护整个项目的组件状态,而Vuex就是用来处理这个问题的。


8646214-1e99cdfbd72b2960.png
vuex机制的数据流动

在项目中使用Vuex

安装: npm install --save vuex
导入: import Vuex from 'vuex'
使用vuex: Vue.use(Vuex)
创建仓库store, 配置vue信息:

 const store = new Vuex.Store({ 
  // vuex 的配置信息 
})

使用配置:

new Vue({
  el: '#app',
  router: router,
  // 使用vuex
  store: store,
  component: {app},
  tmeplate: '<app/>'
})

  仓库 store包含了应用的数据(状态)和操作过程。Vuex里的数据都是响应式的,任何组件使用同一store时,只要store的数据发生了变化,对应的组件也会立即更新。

Vuex 怎么用

  vuex这么强,那它怎么用?数据状态管理如何实现?

| 搭好vuex框架

  接下来为了提高学习效率,我们采用总分形式直接入手实例,假设有store.js如下

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)
import request from './module/request'
import nav from './module/nav'
import breadcrumb from './module/breadcrumb'
let store = new Vuex.Store({
    modules: {
        request,
        nav,
        breadcrumb
    }
});

export default store;

  在代码中可以看到创建了一个仓库store,而配置信息是一个modules,它的值是从其他文件导入的,什么意思?其实这只是vuex更加规范的管理每一种类型或功能数据状态的规范而已。如案例中有三种,request用于管理异步请求的数据状态,nav用于管理导航信息的数据状态,breadcrumb用于管理面包屑的数据状态。这就是vuex中module选项的用法。

| 配置一个真正的vuex文件

  分好数据类型之后,我们开始配置一个真正的vuex配置信息,假设在./module/breadcrumb.js中有如下配置

export default {
  // state选项用来存放 仓库中各组件托管的数据状态
 state: {
    message: 'store源数据',
    list: [3, 8, 13, 24, 5]
  },
  // mutations选项定义组件中更新数据的方法
  // 组件只能通过这种办法修改state中的数据
  mutations: {
   // 参数state就是上一个选项state,第二个是组件中传递过来要更新的数据
   changeMes (state, val) {
     state.message = val
   },
   resetMes (state, val) {
     state.message = val
   }
  },
  // 仓库中统一进行数据处理的地方,功能类似组件中的computed
  getters: {
    listLength: (state, getters) => {
      return getters.filteredList.length
    }
  },
  // actions实现异步修改数据,不能用mutation实现(数据不能及时更新)
  actions: {
    actionMesAsyn (context) {
      return new Promise(resolve => {
        setTimeout(() => {
          context.commit('changeMes', msg)
          resolve()
        }, 2000)
      })
    }
  }
}

  如案例中所诉,一个仓库可以有一下几个选项

  1. state选项: 用来存放 仓库中各组件托管的数据状态
  2. mutations选项: 定义组件中更新数据的方法,在组件中,只能通过这种办法修改state中的数据,而不能直接调用state修改,仓库的数据流动书单向传递的
  3. getters:选项: 仓库中统一进行数据处理的地方,功能类似组件中的computed
  4. actions选项: 如果修改数据的操作是异步的,不能使用mutations,必须使用actions,否者会出现更新不及时的问题
| 在页面中访问vuex数据

  到目前位置我们已经配置好一个vuex了, 在任何组件,通过调用$store来访问状态信息。如果没有使用module,在组件通常在计算属性中使用

computed: {
  storeData: this.$store.state.list
}

如果使用了module,则需要加模块名如本例中的breadcrumb

this.$store.state.breadcrumb.list

对于getters中处理过的数据状态,使用

this.$store.getters.filterList

对于mutations中的方法,在组件中使用commit来触发事件

this.$store.commit('increment', 5)

猜你喜欢

转载自blog.csdn.net/weixin_34417635/article/details/87229849