Vuex学习笔记--01

Vuex是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

什么是“状态管理模式”?

让我们从一个简单的 Vue 计数应用开始:

new Vue({
  // state
  data () {
    return {
      count: 0
    }
  },
  // view
  template: `
    <div>{{ count }}</div>
  `,
  // actions
  methods: {
    increment () {
      this.count++
    }
  }
})

这个状态自管理应用包含以下几个部分:

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

但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:

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

对于问题一:传参的方式对于多层嵌套的组件将会非常的繁琐,并且对于兄弟组件之间的状态传递无能为力,对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。

因此 我们为什么不把组件的共享状态抽取出来,以一个全局单例模式进行管理呢?
在这种模式下,我们的组件树构成了一个巨大的“视图” 不管在树的哪一个位置,任何组件都能够获取状态或者触发行为。

每一个Vuex应用的核心就是store(仓库)store基本上就是一个容器,它包含着应用中大部分的状态,Vuex和单纯的全局对象有以下两点不同:

1.`Vuex`的状态存储是响应式的,当`Vuex`组件从`store`中状态的时候,若`store`中的中的状态发生变化,那么相应的组件也会相应的得到高效的更新。

2.你不能直接更改`store` 里面的数据,改变`store` 中的状态的唯一途径就是显示的

提交(commit)mutation 这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

最简单的store:

// 如果在模块化构建系统中,请确保在开头调用了 Vue.use(`Vuex`);
const store = new Vuex.store({
  state:{
    count:0
  },
  mutations:{
    increment(state){
      state.count++
    }
  }
})

现在,你可以通过 store.state 来获取状态对象,以及通过store.commit方法触发
状态变更:

store.commit('increment')

console.log(store.state.count); // 1

再次强调 我们通过提交mutation的方式,而非直接改变 store.state.count 是因为我们想要更加明确地追踪到状态的变化。这个简单的约束能让你的意图更加明确,
这样你在阅读代码的时候更容易地解读应用内部的状态改变,此外,这样也能让我们有机会去实现一些记录每次状态的改变,保存状态快照的调试工具,有了它,我们甚至可以实现如时间穿梭般的调试体验。。

由于store中的状态是响应式的,在组件中调用store的状态简单到仅需要在计算属性中返回即可,触发变化也仅仅是在组件中methods中提交mutation

State:单一状态树

Vuex使用单一状态树-——是的,用一个对象就包含了全部的应用层级状态,至此它便作为一个“唯一数据源”而存在,这也意味着,每一个应用将仅仅包含一个store实例。

在Vue组件中获得Vuex状态:

那么我们如何在Vue组件中展示状态呢?由于Vuex的状态存储是响应式的,从store
实例中读取状态的最简单的方法就是在计算属性中返回某一个状态。

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

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

然而,这种模式导致组件依赖全局状态单例,在模块化的构建系统中,在每个需要使用的
state 的组件中需要频繁地导入,并且在测试组件时候需要模拟状态。

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
      }
    }
  }

mapState 辅助函数:

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

  // 在单独构建的版本中辅助函数为 `Vuex.mapState`
  import { mapState } from 'Vuex'

  export default {
    // ...
    computed: mapState({
      // 箭头函数可使代码更简练
      count: state => state.count,
  
      // 传字符串参数 'count' 等同于 `state => state.count`
      countAlias: 'count',
  
      // 为了能够使用 `this` 获取局部状态,必须使用常规函数
      countPlusLocalState (state) {
        return state.count + this.localCount
      }
    })
  }

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

  computed: mapState({
    // 映射this.count 为 `store`.state.count;
    'count'
  })

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

computed: {
  localComputed () { /* ... */ },
  // 使用对象展开运算符将此对象混入到外部对象中
  ...mapState({
    // ...
  })
}

组件仍然保有局部状态:

使用Vuex并不意味着你需要将所有的状态都放入Vuex,虽然将所有的状态
放到Vuex会使得状态变化更加显式和易于调试,但是也会使得代码变得冗长和不直观,如果有些状态严格属于单个组价,最好还是作为组件的局部状态。

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

推荐阅读更多精彩内容

  • Vuex 是什么? ** 官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式**。它采用集中...
    Rz______阅读 2,300评论 1 10
  • vuex学习笔记 vuex是什么? Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存...
    EL_PSY_CONGROO阅读 768评论 0 0
  • vuex理解。 Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件状态,...
    GXW_Lyon阅读 274评论 0 0
  • 概要 官方解释Vuex是一个专为Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态...
    许小花花阅读 447评论 0 0
  • 学习目的 了解和熟练使用 VueX,能够在实际项目中运用。 VueX介绍 Vuex 是一个专为 Vue.js ...
    _1633_阅读 2,788评论 0 7