Vuex介绍。

基本介绍

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex的主要作用是将状态(在data中的属性需要共享给其他vue组件使用的部分)单独拎出来,应用统一的方式进行处理,保证各组件间的状态同步(以及同一组件再次显示时的状态保持)。

通俗来说:

Vuex 就是前端为了方便数据的操作而建立的一个”前端数据库 ”
不同的模块组件能通过统一的方法获取,修改数据内容
store>仓库
state>源数据
mutation>Mutations 就是我们把数据存入数据库的 API,用来修改state 的唯一方法
getter> getters 是我们从数据库里取数据的 API,是一个”纯函数“,不会对原数据造成影响的函数

它规定了一些需要遵守的规则:

应用层级的状态应该集中到单个 store 对象中。
提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。
异步逻辑都应该封装到 action 里面。

应用场景

Vuex采用和Redux类似的单向数据流的方式来管理数据。用户界面负责触发动作(Action)进而改变对应状态(State),从而反映到视图(View)上。这个状态自管理应用包含以下几个部分:

state,驱动应用的数据源;
view,以声明方式将 state 映射到视图;
actions,响应在 view 上的用户输入导致的状态变化。

以下是一个表示“单向数据流”理念的极简示意:

这里写图片描述

当搭建中,大型组件化的SPA应用,必定会牵扯到多个组件间的通信,单向数据流的简洁性很容易被破坏:

多个视图依赖于同一状态。
来自不同视图的行为需要变更同一状态。

为了解决以上问题,应用Vuex,把组件的共享状态抽取出来,以一个全局单例模式管理。在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!

这里写代码片

vuex安装及配置

安装

利用npm包管理工具,进行安装 vuex。在控制命令行中输入下边的命令就可以了

npm install vuex –save
注意:这里一定要加上 –save,因为你这个包我们在生产环境(devDependencies)中是要使用的。

配置

  1. 新建一个store文件夹,并在文件夹下新建index.js文件,文件中引入我们的vue和vuex,引入之后用Vue.use进行引用。

    这里写图片描述

  2. 在main.js 中引入新建的vuex文件,然后 , 在实例化 Vue对象时加入 store 对象 :

 import storeConfig from './vuex/store'
 new Vue({
      el: '#app',
      router,
      store,//使用store
      template: '<App/>',
      components: { App }
    })

核心概念

state

State负责存储整个应用的状态数据(state就是根据你项目的需求,自己定义一个数据结构,是我们单页应用程序中的共享值),一般需要在使用的时候在跟节点注入Store(相当于仓库)对象(store中至少要注入两项,state 和 mutation)。

在组件使用的过程中,如果想要获取对应的状态你就可以直接使用this.$store.state获取,当然,也可以将
状态对象赋值给内部对象,也就是把index.js中的值,赋值给我们模板里data中的值。有三种赋值方式

  1. 通过computed的计算属性直接赋值
    computed:{count(){return this.$store.state.count;}}
  2. 通过mapState的对象来赋值
    import {mapState} from 'vuex'; computed:mapState({count:state=>state.count })
    理解为传入state对象,使用ES6的箭头函数来给count赋值,修改state.count属性。
  3. 通过mapState的数组来赋值
    computed:mapState(["count"])

getters

getters从表面是获得的意思(可以认为是 store 的计算属性),可以把他看作在获取数据之前进行的一种再编辑,相当于对某些状态做二次处理( 对数据的一个过滤和加工 )。getters 是一个纯函数,接收参数 state,返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

getters基本用法:

比如我们现在要对index.js文件中的count进行一个计算属性的操作,就是在它输出前,给它加上100.我们首先要在index.js里用const声明我们的getters属性。

写好了gettters之后,我们还需要在Vuex.Store()里引入,在index.js里的配置算是完成了,我们需要到模板页对computed进行配置。在vue 的构造器里边只能有一个computed属性,如果你写多个,只有最后一个computed属性可用,所以要对上节课写的computed属性进行一个改造。改造时我们使用ES6中的展开运算符”…”。

或者用mapGetters简化模板写法,将 store 中的 getter 映射到局部计算属性,如下:

这里写图片描述

mutations

Mutations的中文意思是“变化”,利用它可以更改状态(是操作state的唯一方法,即只有mutations方法能够改变state状态值),Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

这里写图片描述

Mutation 需遵守 Vue 的响应规则:

  1. 最好提前在你的 store 中初始化好所有所需属性。
  2. 当需要在对象上添加新属性时,你应该
    使用 Vue.set(obj, ‘newProp’, 123), 或者以新对象替换老对象。
    例如,利用 stage-3 的对象展开运算符我们可以这样写:
    state.obj = { …state.obj, newProp: 123 }

你可以在组件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store,如上图)。

store.commit(mutationName)是用来触发一个mutation的方法。需要记住的是,定义的mutation必须是同步函数,否则devtool中的数据将可能出现问题,使状态改变变得难以跟踪。

Action

Actions也可以用于改变状态,不过是通过触发mutation实现的,重要的是可以包含异步操作。其辅助函数是mapActions与mapMutations类似,也是绑定在组件的methods上的。如果选择直接触发的话,使用this.$store.dispatch(actionName)方法。关于action和mutations的区别有以下几点:

Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
Action 还是得通过 mutation 方法来修改state

同样是之前的increment方法,我们分别用同步和异步的action来验证上面所说的与mutations的不同之处:

actions: { //定义Actions
    increment (context) {
      context.commit('increment')  //context上下文对象,这里你可以理解称store本身
    },
    incrementAsync (commit) {// 延时1秒  
      setTimeout(() => {
        context.commit('increment') //{commit}:直接把commit对象传递过来,可以让方法体逻辑和代码更清晰明了
      }, 1000)
    }
  }

context是与 store 实例具有相同方法和属性的对象。可以通过context.state和context.getters来获取 state 和 getters。不同于mutations使用commit方法,actions使用dispatch方法,this.$store.dispatch(‘incrementAsync’)。

在组件中分发 Action:

import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
    })
  }
}

module

module:状态管理器的模块组操作。使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。这时候我们就需要把我们状态的各种操作进行一个分组,分组后再进行按组编写。

Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割。

声明模块组:在vuex/index.js中声明模块组,我们还是用我们的const常量的方法声明模块组。声明好后,我们需要修改原来 Vuex.Stroe里的值:代码如下

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

在模板中使用:现在我们要在模板中使用count状态,要用插值的形式写入。如果想用简单的方法引入,还是要在我们的计算属性中rutrun我们的状态。

<h3>{{$store.state.a.count}}</h3>     //插值写入

computed:{   //计算属性中rutrun我们的状态
   count(){
         return this.$store.state.a.count;
     }
 }

Plugins

插件就是一个钩子函数,在初始化store的时候引入即可。比较常用的是内置的logger插件,用于作为调试使用。
在插件中不允许直接修改状态——类似于组件,只能通过提交 mutation 来触发变化。
通过提交 mutation,插件可以用来同步数据源到 store。

const myPlugin = store => {
  // 当 store 初始化后调用
  store.subscribe((mutation, state) => {
    // 每次 mutation 之后调用
    // mutation 的格式为 { type, payload }
  })
}
//然后像这样使用:
const store = new Vuex.Store({
  // ...
  plugins: [myPlugin]
})

收集源:
https://www.jianshu.com/p/d6f7e11f18af
http://blog.csdn.net/sinat_17775997/article/details/54943797
https://vuex.vuejs.org/zh-cn/plugins.html
http://blog.csdn.net/h5_queenstyle12/article/details/75386359
https://zhuanlan.zhihu.com/p/24357762

Logo

前往低代码交流专区

更多推荐