挑战全网最幽默的Vuex系列教程:第二讲 Vuex旗下的State和Getter

先说两句

上一讲 「Vuex 究竟是个什么鬼」,已经完美诠释了 Vuex 的牛逼技能之所在(纯属自嗨)。若是把 Vuex 比喻成农药里面的刘备,那就至关于你如今已经知道了刘备他是一个会打枪的力量型英雄,并且他打的枪仍是双排量的,认识到这一点后,那么接下来就是要了解他究竟是如何打枪的,是左手打,仍是右手打,仍是双手一块儿端着枪打?html

一样,咱们已经知道了 Vuex 就如同一个全局的管理员同样,帮着咱们统一管理着项目的共享数据,那它究竟是经过什么样的方式去管理的呢?咱们应该如何与这个管理员进行沟通和交流,才能有效的访问和操做这些共享数据呢?前端

再说一句

Vuex 的内脏由五部分组成:State、Getter、Mutation、Action 和 Module。关于这五个部分,我会分为多个章节来进行详细阐述,这一讲就先和你们一块儿完全搞定 State 和 Getter。vue

固然,在实际应用中,这五个部分并非必须的,你须要用到什么就添加什么。可是通常再怎么简单的 Vuex,也至少会由 State 和 Mutation 构成,不然你就该考虑 Vuex 是否有存在的必要了。vuex

最后,舒适提示,文档示例代码使用了 ES2015 的语法,若是你还没了解过的话,先戳此了解了解缓存

单一状态树

Vuex 使用的是**「单一状态树」,根据官方的描述,可能有点懵圈,不过不要紧,这里咱们一块儿来详细了解下到底什么是「单一状态树」**。抛开单一状态,咱们先来看一下这里的树是什么意思。babel

组织架构

如上图是一个公司的组织架构,它的这种层级其实就属于一种树形的结构,总经理就是树的主干,其余各部门或者职业,都属于树的分支。架构

通常状况下,一个公司只会有这么一个树形架构,若是有两个平等的总经理,那么公司在管理上极可能就会出现矛盾,下面的人到底听谁的呢,是吧!app

好,如今我们再来看下官方所叙述的**「单一状态树」**:框架

一、用一个对象(主干)就包含了所有的(分支)应用层级状态。 二、每一个应用(公司)将仅仅包含一个 store 实例对象(主干)ide

单一状态树让咱们可以直接地定位任一特定的状态片断,在调试的过程当中也能轻易地取得整个当前应用状态的快照。

State

咱们再回过头来看一下以前那个简单的 Store 示例代码:

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

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  }
})

那么咱们如何在 Vue 组件中展现状态呢?因为 Vuex 的状态存储是响应式的,从 store 实例中读取状态最简单的方法就是在计算属性中返回某个状态,以下:

// 建立一个 Counter 组件
const Counter = {
  data() { return {} },
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}

每当 store.state.count 变化的时候, 都会从新求取计算属性,并刷新界面。

须要注意的是,若是你把 store.state.count 放在 data 中, store.state.count 的变化是不会主动触发界面刷新的,固然,也不能直接这样:<div>{{ store.state.count }}</div> ,由于在模板中是没法直接访问到 store 对象的,因此这样写无疑会报错。

这种模式依赖于全局的管理员 store,若是模块多了,意味着每一个模块或者页面只要用到了这个 state 里面的数据,都得把 store 引入进来,这样的操做确实有点难受。固然,官方确定是不容许有这样使人抓狂的操做出现的:

Vuex 经过 store 选项,提供了一种机制将状态从根组件 “注入” 到每个子组件中(需调用 Vue.use(Vuex)):

const app = new Vue({
  el: '#app',
  // 把 store 对象提供给 “store” 选项,
  // 这能够把 store 的实例注入全部的子组件
  store,
  // 子组件
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})

经过在根实例中注册 store 选项,该 store 实例会注入到根组件下的全部子组件中,且子组件能经过 this.$store 访问到。让咱们更新下 Counter 的实现:

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

Vuex 的状态当然好用,可是也不要滥用:

使用 Vuex 并不意味着你须要将全部的状态放入 Vuex。虽然将全部的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。若是有些状态严格属于单个组件,最好仍是做为组件的局部状态。你应该根据你的应用开发须要进行权衡和肯定。

Getter

有时候,咱们会发现 State 中的数据,并非咱们直接想要的,而是须要通过相应的处理后,才能知足咱们的需求。

好比在一个组件中,咱们须要把 state 中的日期 date 转换成星期几来展现:

computed: {
  weekDate () {
    return moment(this.$store.state.date).format('dddd'); 
  }
}

注意:这里的 moment 是一个第三方日期处理类库,使用以前须要导入。

若是只有一个组件须要这样作还好,但若是在不少组件中,都须要这么转换的话,那就得在每个组件中都须要把这个函数复制过去。并且,一旦产品经理心情很差,不想用星期几来显示,想直接用 2018-10-30 11:12:23 这种方式来显示日期,那你就得在全部用到它的组件中去更改日期格式化的方法,岂不难受至极。就算你把它单独抽取出来做为一个公共的函数,各类导入也麻烦,最重要的是很差统一管理。

因此,这个时候,Vuex 又引入了一个牛逼的玩意儿,Getter。咱们能够把它当成 store 中的计算属性(computed)。

就像计算属性同样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被从新计算。

咱们看看这两个例子,着重注意下里面的注释:

const store = new Vuex.Store({
  state: {
    date: new Date()
  },
  getters: {
    // Getter 接受 state 做为其第一个参数
    weekDate: state => {
      return moment(state.date).format('dddd'); 
    }
  }
})
getters: {
  // Getter 还也能够接收 getters 做为第二个参数
  dateLength: (state, getters) => {
    return getters.weekDate.length;
  }
}

不但如此,Getter 还会将 store.getters 对象暴露出去,你能够以属性的形式访问这些值:

console.log(store.getters.weekDate)

咱们能够很容易地在任何组件中使用它:

computed: {
  weekDate () {
    return this.$store.getters.weekDate
  }
}

如今需求又变了,每一个模块要显示的 weekDate 的格式不同,有的显示所有日期,有的须要显示星期几,怎么办?

好办,那就给 Getter 传参呗,可是怎么传呢?

由于 Getter 在经过属性访问时是做为 Vue 的响应式系统的一部分缓存其中的,因此是不能直接 store.getters.weekDate('MM Do YY'),由于 weekDate 并非一个函数,它仅仅只是一个属性而已。

那么既然属性不能传参,怎么办呢?那咱们就想办法把这个属性变成一个函数不就好了。

getters: {
  // 返回一个函数,就能够传参了
  weekDate: (state) => (fm) => {
    return moment(state.date).format(fm ? fm : 'dddd'); 
  }
}

使用以下:

store.getters.weekDate('MM Do YY')

写在最后

可能看过官方文档的童鞋会好奇,为何没有讲解那些辅助函数,好比 mapStatemapGetters。别担忧,后面会有专门的一个章节来进行讲解,由于我发现这些辅助函数(包括后面的 mapMutationsmapActions)都是为了解决同一个问题而生,只是形式不一样罢了,因此还不如拆出来一块儿讲,或许效果会更好。

对于官方我我的以为写得比较通俗易懂的地方,就直接引用了进来。若是有疑问或者对于个人理解有疑问的地方,欢迎留言。

固然,这种技术型的文章在不一样阶段的人看来,确定会有不同的体会。我知道,确定会有不足的地方,我也会继续慢慢的完善。若是文章对你们有帮助的话,欢迎点赞和转载,谢谢!

转载声明:

做者:大宏说

原文连接: https://www.jianshu.com/p/120eaf50331c

后记

以上就是胡哥今天给你们分享的内容,喜欢的小伙伴记得点赞收藏呦,关注胡哥有话说,学习前端不迷路,欢迎多多留言交流...

胡哥有话说,一个有技术,有情怀的胡哥!现任京东前端攻城狮一枚。 胡哥有话说,专一于大前端技术领域,分享前端系统架构,框架实现原理,最新最高效的技术实践!

相关文章
相关标签/搜索