最快速理解Vuex的方法

·  阅读 707

最快速理解Vuex的方法

对于初学者,学vue简单,但是当第一次遇到Vuex概念的时候,理解难度往往骤然陡峭,会让人感到挫败感,挫败感来自于大多数教程文章用了大量篇幅来介绍Vuex较为复杂,却看完感觉没什么作用(不知道如何运用)的实现模式,本文就是要简而化之,让你秒懂。

本质

Vuex 术语定义叫做『全局状态管理』,其实质就是一个全局变量,可以供不同组件间调用,更新,自动通知。 当然在具体实现的时候,这个全局变量其实是一个全局对象:this.$store,

所以记住这个store对象,它就是vuex。

来龙去脉

facebook以前在搞他的那个网页app的时候,尤其是在做消息模块的时候,各种全局通知和聊天信息,组件间互相通信非常混乱,老出bug,于是他们就发明了一种解决这个问题的设计模式,叫做 FLUX。

这个设计模式是按照怎样的原则来解决通信混乱的问题呢?

1. 单一数据源(Single Source of Truth)

也就是说,store是一个唯一全局变量(对象),不能搞多个,搞多个就乱了。

2. 数据只读(Data is Read-Only)

这个只读不是说完全不让读,而是不能让 store外部直接操作数据,必须通过store内部方法(mutations)来操作数据。

3. 数据更新必须是同步的(Mutations Are Synchronous)

异步数据会很混乱,必须是同步操作模式。

为什么是这3个原则,你不用管,反正facebook反复实验,按照这三个原则设计,问题就搞定了。

facebook 按照FLUX设计模式,开发了大名鼎鼎的Redux库,React必备搭配。Vue看见此需求群众呼声很高,也配套了一个,也就是Vuex。

所以,Redux和Vuex都是对Flux这种设计模式的实现,别混为一谈。

store的内部

store 这个对象,肯定是挂载Vue上面的,就是按照下面这种方式挂:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
  state: {
  },
  actions: {
  },
  mutations: {
  },
  getters: {
  },  
  modules: {
    
  }
})
export default store

复制代码

我们看到有这些 state,actions,mutations,modules这些属性, 为啥一个实质是变量的对象搞这么复杂,这其实和Flux设计模式有关系,它的本质就是:「我的事情我自己来,你们(组件)别直接操作我,告诉我就行,我自己来」。

下面一个一个讲:

state

state,这个所谓的状态,其实就是数据,全局的数据。

你在一个vue组件里,这样写,就可以获取这个数据:

computed: {
    count () {
      return this.$store.state.count
    }
  }

复制代码

这个count就是state下面定义的一个数据,怎么定义的呢:

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

复制代码

在那个挂载store对象的文件里,这样定义,非常符合直觉。 你这边写0,上面那边就读出0,你这边改成2了,上面就自动变成2,监听是默认的。

mutations

接着上面讲,你怎么把count改成2呢?

this.$store.state.count = 2
复制代码

这样是不行的,前面讲过,你不要直接动store的数据,你需要告诉它,让他自己来处理。

所以store自己先得有个处理方法,这就是mutations:

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})
复制代码

这个方法就是increment,很符合直觉。

你在组件那里要做就是通知store,激活这个increment,怎么写呢:

this.$store.commit('increment')
复制代码

注意,讲到这里,单词越来越多了,英语不好的同学需要记住对应关系,commit就是触发一个事件,通知store执行mutations下的某个方法。

getters

Vue 组件下面有个computed属性,一个组件自己用没问题,如果多个组件下都想使用一个共有的computed属性,那么这就是 store里面的getters。

唉,英语不好真伤心啊,起那么多名字其实是一个东西。

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动态属性doneTodos,就是拿state静态属性todos放进一个函数算了一遍。

actions

actions很简单,就是异步的mutations,咦?不对啊,前面我们讲flux三原则的时候,说过数据更新必须是同步的,这个还是英文的问题,Mutations Are Synchronous,说的是mutation,但是有时候我们需要异步去请求数据,这个时候就需要actions。

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment:function ({ commit }) {
      axios.get('/add').then((response) => {
        commit('increment')
      }, (err) => {
        console.log(err)
      })
  }
})

复制代码

怎么触发actions里的increment呢?

this.$store.dispatch('increment')

复制代码

我的天,又多了一个单词:dispatch, 知道为啥新手会觉得困难了吧?

官方文档给的那个示例其实不是很好,官方只是说action必须commit,但理解actions的关键在于它的使用场景是异步,因为flux的实质是同步,所以异步拿到数据后,必须通过mutation去更新数据,所以必须commit;

Modules

很多组件都共用store里面state来存数据,组件多了,时间久了,不利于管理。 于是就有这个modules模块

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`'s state
store.state.b // -> `moduleB`'s state
复制代码

主要观察

  modules: {
    a: moduleA,
    b: moduleB
  }
复制代码

在调用的时候,就可以分别调用

store.state.a // -> `moduleA`'s state
store.state.b // -> `moduleB`'s state
复制代码

小结

看完这篇文章,你再去看官方文档,应该没问题了,但是如果我把官方文档的例子和其他信息全搬过来,你肯定会晕。

vuex很简单,难就难在那几个设计原则你不知道,还有就是单词有点多,记不过来。

看完文档后,你实验几次就知道怎么运用了。

larabase.com/post/193

分类:
前端
标签:
分类:
前端
标签: