前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布

vuex

作者头像
epoos
发布2022-06-06 15:47:37
1K0
发布2022-06-06 15:47:37
举报
文章被收录于专栏:epoos.com

Vuex是一个专门为Vue.js应用程序开发的状态管理模式。 它采用集中式存储管理应用的所有组件状态,并以相应的规则保证状态以一种可预测的方式发生变化。

状态管理包含以下几部分

代码语言:javascript
复制
1.state 驱动应用的数据源
2.view 以声明方式将state映射到视图
3.action 相应在 view 上的用户输入导致的状态变化

这三个状态之间互相交互,就形成了vue的单向数据流

但是这个单项数据流模式是很容易被破坏的。 如:

代码语言:javascript
复制
1.多个视图依赖于同一状态。
2.来自不同视图的行为需要变更同一状态。

对于第一种状态,可以通过传参的形式解决,但是对于兄弟节点之间的状态传递就很麻烦了。 第二种状态,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。

这些做法都有其局限性,那么有什么办法能解决这些问题呢?

这就是vuex被设计出来的原因了。它的出现就是为了解决这些问题。

核心概念

代码语言:javascript
复制
state:vuex使用单一状态树,一个对象包含了全部应用层级的状态,是唯一数据源。

由于vuex的状态是存储是响应式的,从store实例中读取状态,最简单的方法就是在计算属性中返回某个状态。

除此之外,vue 还通过store选项,提供了一种机制,将状态从根组件 注入到每一个子组件。

代码语言:javascript
复制

import Vue from 'vue'
import Vuex from 'vuex'
import * as actions from './actions'
import * as getters from './getters'
import state from './state'
import mutations from './mutations'

Vue.use(Vuex)

const debug = process.env.NODE_ENV !== 'production'

let store = new Vuex.Store({
  actions,
  getters,
  state,
  mutations,
})


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

通过在根实例中注册store选项,该store实例会注入到根组件下所有子组件中 子组件能通过 this.$store 访问到。

代码语言:javascript
复制
getter: 通过getter获取属性,可以在获取state的时候对属性进行过滤或者计算。

getter的返回值跟计算属性一样,会被缓存,只有当依赖属性变化的时候才会重新计算,可以看做是store的计算属性。 getter可以返回一个函数,来实现给getter传参。 当getter返回的是一个函数的时候,通过方法访问的时候,每次都会去进行调用,不会缓存结果。

代码语言:javascript
复制
mutation:更改vuex中store状态的唯一方法就是提交mutation

vuex中的mutation类似于事件 每个mutation都有一个字符串 事件类型(type)和一个回调函数(handler) 这个回调函数就是我们实际进行状态更改的地方,它接受一个state作为第一个参数。

定义一个mutation

代码语言:javascript
复制
const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state, n) {
      // 变更状态
      state.count++
    }
  }
})

调用一个mutation

代码语言:javascript
复制
// 字符串的方式调用
store.commit('increment', n)

// 对象的方式调用cc
store.commit({
  type: 'increment',
  amount: 10
  ... // 更多字段
})

第二个参数‘n’叫做载荷,通常情况n是一个对象,这样方便传更多的参数。

特别注意:mutation必须是同步函数。 那么如果是异步请求怎么办呢?

此时,就需要用到另一个核心概念Action了

代码语言:javascript
复制
action:action和mutation类型,区别在于,action是提交一个mutation而直接变更状态。

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

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象作为参数。 context可以有commit、state、getters、 因此,可以直接通过参数调用commit触发mutation。

代码语言:javascript
复制
// 定义一个action
actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

// 调用一个action action也支持荷载,支持对象和字符串的方式传参
// 以载荷形式分发
store.dispatch('incrementAsync', {
  amount: 10
})

// 以对象形式分发
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

store.dispatch可以处理被触发action的处理函数返回的Promise,并且 store.dispatch仍旧返回Promise

代码语言:javascript
复制
// 定义异步的action
actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

// dispatch一个promise
store.dispatch('actionA').then(() => {
  // ...
})
代码语言:javascript
复制
module:将store分割成模块,每个模块拥有自己的state、mutation、action、getter、嵌套子模块等。这个模块就是module

如果store非常大的时候,非常不好管理,这时候就可以将其分割为小的module了。

代码语言:javascript
复制
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,接收的第一个参数是模块的局部状态对象。 对于模块内部的 action,局部状态通过 context.state 暴露出来,根节点状态则为 context.rootState 对于模块内部的 getter,根节点状态会作为第三个参数暴露出来

模块命名空间

默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。 如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块

代码语言:javascript
复制
const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true, // 待命名空间的模块,(命名空间控制属性会继承)
    }
  }
})

相关链接

[vuex]https://vuex.vuejs.org/zh/

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 核心概念
    • 模块命名空间
    • 相关链接
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档