Vuex 起步

为什么有 Vuex?

也许你已经学习过 Vue 组件通信的方式了,知道父传子通过props,子传父通过this.$emit。这两种方式有时确实很好用,也很简单。当然,也许你还了解 事件总线 这种方法,但一般很少用它,在思想层面,事件总线 与 Vuex 是类似的。既然如此,何不直接使用 Vuex 呢?

如果你有使用 vue-router 经验的话,也知道组件的渲染除了直接引入,还有 <router-view>——路由视图可以渲染组件。

propsthis.$emit是在直接引入时才能使用。使用vue-router渲染组件的话便没法再使用上述几种方法传递数据。并且,如果你的数据在应用的许多地方都使用到了,且这种数据的改变牵一发而动全身的话,就必须使用 Vuex。

单向数据流

什么是单向数据流?

想一想,当把一些广泛使用的数据抽离到 vuex 中后,便会有一些数据是从 vuex 流向各个组件的。还有一部分数据保留在 dataprops 中。这些数据杂糅在一起,本身就已经比较麻烦了。

如果还有数据从 vuex 流向各个组件,这些数据被滥用,那么数据的来源和去向将难以循迹,在维护组件时会非常头疼。

例如,某个数据存储在 state 中,这个数据在异步请求数据下来后需要进行更新,只有在 state 中更新后数据流向全局,不能在某个组件里发起请求就直接在其页面上渲染,这会导致数据的流向变得混乱。

拿父传子、子传父举例,为什么传递一个数据需要使用两种方法?一个使用props,一个使用this.$emit?这本身就是一种单项数据流,绝不允许数据在组件间随意传递。

vuex 也是这样,数据只能从其内部流向组件。

Vuex 是什么?

Vuex 其实就是一个集中管理数据状态的地方,官方之所以称之为 状态管理 而不是 数据管理,原因在于这里存储的数据都是动态的,随时改变且发射到全局各个地方。

Vuex 应用的核心在于一个 store,也就是一个仓库。仓库的作用就是用来存放物品的。store 里有五个功能区域:

// 引入 Vue
import Vue from 'vue'
// 引入 Vuex
import Vuex from 'vuex'

// 全局使用
Vue.use(Vuex)

// 定义一个仓库
const store = new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {}
})

// 导出这个仓库
export default store

state

第一个功能,是 state,即状态的意思,这里存放所有的全局数据,这里是仓库的唯一存储区域。

const store = new Vuex.Store({
  // 数据放在这里
  state: {}
})

mutations

第二个功能,是 mutations,这里保存所有更改 state 中数据的方法。也就是说,state 中的数据不能直接改变,所有的改变都要经过 mutations 方法。

例如,state 中有一个 number,值为 0:

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

要想改变这个 number 的值,必须在 mutations 里定义一个方法:

const store = new Vuex.Store({
  state: {
    number: 0
  },
  mutations: {
    changeNumber (state) {
      state.number++
    }
  }
})

可以看到,这个自定义方法接收 state 对象作为参数,并对 state 内部数据进行更改。

当然,这个自定义方法 changeNumber 需要一个触发条件,即,哪个组件用到了 number,并且希望更改它,就可以触发这个方法。

actions

第三个功能是 actions。actions 存在的意义是为了执行异步的对 state 的更改操作。也就是说,所有通过网络请求改变 state 数据的操作都必须经过 actions。但 actions 的作用只是一个异步请求更改数据的集中,要改变 state 中的数据还是需要提交 mutations 中的方法。也就是说,actions 的作用其实只是将数据更改的同步操作与异步操作区分开而已。这样利于数据的维护与管理,对于那些异步更改的数据可以更快定位。

actions: {
  // 执行注册请求,异步更新 token 与 user 信息】
  async registerFunc ({ commit }) {
    try {
      const res = await register()
      if (res.status === 200) {
        // 这里的 SaveToken 就是定义在 mutations 里的方法,actions 想要改变数据就必须提交这个方法
        commit('SaveToken', `Token ${res.data.user.token}`)
        commit('SaveUser', res.data.user)
    }
    return res
  } catch (err) {
    return Promise.reject(err.response)
  }
},

getters

getters 可以看作 vuex 中的计算属性。其实,就是 state 中的衍生状态。例如 state 中有一个数组,在组件中需要用到这个数组的一些过滤项。这时就可以使用 getters 方法,且和 computed 属性一样,这些数据会被缓存,只有更改后才会重新渲染。

getters 接收 state 作为第一个参数:

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

getters 接收其他 getters 作为第二个参数:

getters: {
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}

modules 因为比较难,本次不做介绍。

前面提到了这些方法的作用,但没有提到如何在组件中使用他们。其实,因为是直接在全局注册的 Vuex,可以在任何地方使用 Vuex 中的数据。

例如,想要使用 state 中的数据,可以通过:

// 模板中
$store.state.数据

// js 中
this.$store.state.数据

使用 mutations:

this.$store.commit('方法名')

使用 actions:

this.$store.dispatch('方法名')

使用 getters:

this.$store.getters.数据

不仅仅是组件,在 JS 文件中也可以使用 store中的数据。只需要引入即可;

import store from '../store/index'

好了,这就是 Vuex 的简单入门。后面我们会讲到传递参数以及其他的更为进阶的用法。欢迎关注。

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

推荐阅读更多精彩内容