Vuex的五个核心属性

Vuex的五个核心概念

本文参考自Vue文档,说的非常详细,建议看文档。

Vuex是什么?

VueX 是一个专门为 Vue.js 应用设计的状态管理架构,统一管理和维护各个vue组件的可变化状态(你可以理解成 vue 组件里的某些 data )。

Vue有五个核心概念,state,getters,mutations,actions,modules。本文将对这个五个核心概念进行梳理。

总结

state => 基本数据

getters => 从基本数据派生的数据

mutations => 提交更改数据的方法,同步!

actions => 像一个装饰器,包裹mutations,使之可以异步。

modules => 模块化Vuex

State

state即Vuex中的基本数据!

单一状态树

Vuex使用单一状态树,即用一个对象就包含了全部的状态数据。state作为构造器选项,定义了所有我们需要的基本状态参数。

在Vue组件中获得Vuex属性

我们可以通过Vue的Computed获得Vuex的state,如下:

const store =new Vuex.Store({

    state: {

        count:0    }

})

const app =new Vue({

    //..    store,

    computed: {

        count: function(){

            returnthis.$store.state.count

        }

    },

    //..})

每当store.state.count变化的时候, 都会重新求取计算属性,并且触发更新相关联的 DOM。

mapState辅助函数

当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键。

// 在单独构建的版本中辅助函数为 Vuex.mapStateimport { mapState } from 'vuex'export default {

  // ...  computed: mapState({

    // 箭头函数可使代码更简练count: state => state.count,

    // 传字符串参数 'count' 等同于 `state => state.count`countAlias: 'count',

    // 为了能够使用 `this` 获取局部状态,必须使用常规函数    countPlusLocalState (state) {

      returnstate.count +this.localCount

    }

  })

}

当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。

computed: mapState([

  // 映射 this.count 为 store.state.count'count'])

对象展开运算符

mapState 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。但是自从有了对象展开运算符,我们可以极大地简化写法:

computed: {

  localComputed () //本地计算属性//使用对象展开运算符将此对象混入到外部对象中  ...mapState({

    //..  })

}

对象运算符 

...展开运算符(spread operator)允许一个表达式在某处展开。展开运算符在多个参数(用于函数调用)或多个元素(用于数组字面量)或者多个变量(用于解构赋值)的地方可以使用。

展开运算符不能用在对象当中,因为目前展开运算符只能在可遍历对象(iterables)可用。iterables的实现是依靠[Symbol.iterator]函数,而目前只有Array,Set,String内置[Symbol.iterator]方法,而Object尚未内置该方法,因此无法使用展开运算符。不过ES7草案当中已经加入了对象展开运算符特性。

function test(a,b,c) {

        console.log(a);

        console.log(b);

        console.log(c);

    }

    varargs = [0,1,2];

    test(...args);  // 0  1  2

ES7草案中的对象展开运算符 

ES6中还不支持对对象的展开运算符,但是ES7中将支持。对象展开运算符符可以让我们更快捷地操作对象,如下例子:

let {x,y,...z}={x:1,y:2,a:3,b:4};

    x; //1y;//2z;//{a:3,b:4}

组件仍然保有局部状态

使用 Vuex 并不意味着你需要将所有的状态放入 Vuex。虽然将所有的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。

如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。

getters

即从store的state中派生出的状态。

getters接收state作为其第一个参数,接受其他 getters 作为第二个参数,如不需要,第二个参数可以省略如下例子:

const store =new Vuex.Store({

    state: {

        count:0    },

    getters: {

        // 单个参数countDouble:function(state){

            returnstate.count * 2        },

        // 两个参数countDoubleAndDouble:function(state, getters) {

            returngetters.countDouble * 2        }

    }

})

与state一样,我们也可以通过Vue的Computed获得Vuex的getters。

const app =new Vue({

    //..    store,

    computed: {

        count: function(){

            returnthis.$store.state.count

        },

        countDouble: function(){

            returnthis.$store.getters.countDouble

        },

        countDoubleAndDouble: function(){

            returnthis.$store.getters.countDoubleAndDouble

        }

    },

    //..})

mapGetters 辅助函数

mapGetters 辅助函数仅仅是将 store 中的 getters 映射到局部计算属性,与state类似

import { mapGetters } from 'vuex'export default {

  // ...  computed: {

  // 使用对象展开运算符将 getters 混入 computed 对象中    ...mapGetters([

      'countDouble',

      'CountDoubleAndDouble',

      //..    ])

  }

}

如果你想将一个 getter 属性另取一个名字,使用对象形式:

mapGetters({

  // 映射 this.double 为 store.getters.countDoubledouble: 'countDouble'})

mutations

提交mutation是更改Vuex中的store中的状态的唯一方法。

mutation必须是同步的,如果要异步需要使用action。

每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。(提交荷载在大多数情况下应该是一个对象),提交荷载也可以省略的。

const store =new Vuex.Store({

  state: {

    count: 1  },

  mutations: {

    //无提交荷载    increment(state) {

        state.count++    }

    //提交荷载    incrementN(state, obj) {

      state.count += obj.n

    }

  }

})

你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

//无提交荷载store.commit('increment')//提交荷载store.commit('incrementN', {

    n: 100    })

对象风格的提交方式

我们也可以使用这样包含 type 属性的对象的提交方式。

store.commit({

  type: 'incrementN',

  n: 10})

Mutations 需遵守 Vue 的响应规则

最好提前在你的 store 中初始化好所有所需属性。

当需要在对象上添加新属性时,你应该

使用Vue.set(obj, 'newProp', 123), 或者

以新对象替换老对象。例如,利用对象展开运算符我们可以这样写state.obj = {...state.obj, newProp: 123 }

mapMutations 辅助函数

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

import { mapMutations } from 'vuex'export default {

  //..  methods: {

    ...mapMutations([

      'increment'// 映射 this.increment() 为 this.$store.commit('increment')    ]),

    ...mapMutations({

      add: 'increment'// 映射 this.add() 为 this.$store.commit('increment')    })

  }

}

actions

Action 类似于 mutation,不同在于:

Action 提交的是 mutation,而不是直接变更状态。

Action 可以包含任意异步操作。

我们用如下例子来结束actions:

const store =new Vuex.Store({

  state: {

    count: 0  },

  mutations: {

    increment (state) {

      state.count++    }

  },

  actions: {

    increment (context) {

      setInterval(function(){

        context.commit('increment')

      }, 1000)

    }

  }

})

注意:Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。

分发actions

Action 通过store.dispatch方法触发:

store.dispatch('increment')

其他与mutations类似的地方

Actions 支持同样的载荷方式和对象方式进行分发:

// 以载荷形式分发store.dispatch('incrementN', {

  n: 10})// 以对象形式分发store.dispatch({

  type: 'incrementN',

  n: 10})

mapActions辅助函数

你在组件中使用this.$store.dispatch('xxx')分发 action,或者使用mapActions辅助函数将组件的 methods 映射为store.dispatch调用(需要先在根节点注入store):

import { mapActions } from 'vuex'export default {

  //..  methods: {

    ...mapActions([

      'incrementN'//映射 this.incrementN() 为 this.$store.dispatch('incrementN')    ]),

    ...mapActions({

      add: 'incrementN'//映射 this.add() 为 this.$store.dispatch('incrementN')    })

  }

}

Modules

使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。

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

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 的状态

模块的局部状态

对于模块内部的mutation和getter,接收的第一个参数是模块的局部状态,对于模块内部的 getter,根节点状态会作为第三个参数:

const moduleA = {

  state: { count: 0 },

  mutations: {

    increment (state) {

      // state 模块的局部状态state.count++    }

  },

  getters: {

    doubleCount (state) {

      returnstate.count * 2    },

    sumWithRootCount (state, getters, rootState) {

      returnstate.count + rootState.count

    }

  }

}

同样,对于模块内部的 action,context.state是局部状态,根节点的状态是context.rootState:

const moduleA = {

  // ...  actions: {

    incrementIfOddOnRootSum (context) {

      if((context.state.count + context.rootState.count) % 2 === 1) {

        commit('increment')

      }

    }

  }

}

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

推荐阅读更多精彩内容

  • 安装 npm npm install vuex --save 在一个模块化的打包系统中,您必须显式地通过Vue.u...
    萧玄辞阅读 2,960评论 0 7
  • ### store 1. Vue 组件中获得 Vuex 状态 ```js //方式一 全局引入单例类 // 创建一...
    芸豆_6a86阅读 737评论 0 3
  • Vuex是什么? Vuex 是一个专为 Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件...
    萧玄辞阅读 3,130评论 0 6
  • ### store 1. Vue 组件中获得 Vuex 状态 ```js //方式一 全局引入单例类 // 创建一...
    芸豆_6a86阅读 352评论 0 0
  • Vuex 的学习记录 资料参考网址Vuex中文官网Vuex项目结构示例 -- 购物车Vuex 通俗版教程Nuxt....
    流云012阅读 1,467评论 0 7