Vuex从入门到精通(一)

状态管理

状态的初始化

状态管理,我们应该并不陌生。

举个例子,超市里新进了一批商品,管理员给这些商品分类,建立索引,然后按照顺序放入货架的过程就是最简单的状态管理。

let goods1 = {
  category: 'fruit',
  name: 'apple',
  quantity: 5
}

let goods2 = {
  category: 'supplies',
  name: 'toothbrush',
  quantity: 5
}

let goods3 = {
  category: 'clothes',
  name: 'sweater',
  quantity: 5
}

简单归类后 :

let shop = {
  goods: {
    fruit: [{ name: 'apple', quantity: 5 }],
    supplies: [{ name: 'toothbrush', quantity: 5 }],
    clothes: [{ name: 'sweater', quantity: 5 }]
  }
}

这样,当我们需要某一商品时,很容易根据类目检索到这个商品 :

console.log(shop.goods.fruit.find(f => f.name === 'apple'))
//-> { name: 'apple', quantity: 5 }

状态的改变

当有顾客前来购买商品时,我们需要类似的操作来减少被购买商品的数量 :

shop.goods.fruit.find(f => f.name === 'apple').quantity --

然而在成千上万的交易量背后,你不知道这些商品被购买的详细情况,你甚至不知道上周卖出了多少苹果,你也就无从得知下周该进多少。

所以你需要一个账目来记录商品购买明细 :

let account = {
  appleSold (value) {
    console.log("apple sold " + value)
    shop.goods.fruit.find(f => f.name === 'apple').quantity -= value
  }
}

当卖出苹果时,POS机“滴”一声,记录生成了 :

account.appleSold (5)
//-> apple sold 5

最简单的store

于是,我们得到了一个最简单的store :

let shop = {
  goods: {
    fruit: [{ name: 'apple', quantity: 5 }],
    supplies: [{ name: 'toothbrush', quantity: 5 }],
    clothes: [{ name: 'sweater', quantity: 5 }]
  },
  account: {
    appleSold (value) {
      console.log("apple sold " + value)
      shop.goods.fruit.find(f => f.name === 'apple').quantity -= value
    },
    funcN () { }
  }
}

由此可知,状态管理可以帮助我们更友好的改变状态,同时,跟踪状态变化的轨迹。

Vue(x) er 须知

开始

Vuex 官方文档:

https://vuex.vuejs.org/zh-cn/getting-started.html

Vuex最核心的概念 :

  1. Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
  2. 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。

下面对此拓展:

对象引用

下面这两段代码将输出什么? 先不要往下看, 自己写一下

let store = {
  state: {
    msg: "welcome"
  }
}, copy = store.state;
store.state = {
  hello: "world"
};
console.log(Object.keys(copy));
let store = {
  state: {
    msg: 'welcome'
  }
}, copy = store.state;
store.state.hello = "world";
console.log(Object.keys(copy))

结果如下(如果你都答对了,那么理解和上手Vuex将会很轻松) :

//-> ["msg"]
//-> ["msg", "hello"]

提交和分发

vuex 只是一个工具,或许过了这段时间,过了这个项目,你就不会再用它。

我们要记住的是它留给我们的启示:

不要直接更改状态, 而是通过提交(commit)和分发(dispatch)的方法通知管理者改变对象状态,这是大型项目和复杂状态管理的最佳实践。

Vuex 核心概念

一个完整的 Vuex Store

/**
 * index.js
 */
import axios from 'axios'

const store = new Vuex.Store({
  state: {
    counter: 0
  },
  getters: {
    counter: state => state.counter
  },
  // 可处理异步请求, dispatch 触发
  actions: {
    askPermission ({commit}) {
      axios.get('/url').then((res) => {
        if(res.data.permission)
          commit('addCounter')
      }).catch((err) => {
        console.log('Error: in process "Ask permission".\n Detailed: ' + err)
      })
    }
  },
  // 同步, commit 触发
  mutations: {
    addCounter (state) {
      state.counter ++
    }
  }
})

PS: 仔细研究一下 dispatch & actions,  commit & mutations,  是否有一种似曾相识的感觉?

Look, 看这对 emit & on (事件机制),同样的事件类型,同样的回调函数。

State

单一状态树

Vuex使用单一状态树,一个state对象包含全部应用层状态,使得一个应用只有唯一数据源(SSOT, Single Source of Truth)

这对模块化并不造成影响

state: {
  moduleA: {
    
  },
  moduleB: {
    
  }
}

Getter

state: {
  prop: ''
}

你可以使用store.state.prop直接读取状态的值, 当然也可以使用Getter :

getters: {
  prop = state => state.prop
}

使用Getter的好处在于,你可以从state中派生出一些状态 :

getters: {
  prop = state => state.prop,
  fixedProp = state => state.prop || '暂无'
}

Mutation

Vuex 中的 mutation 类似于事件,有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler),回调函数的接受state作为第一个参数,我们在这里修改状态(state)

state: {
  counter: 0
},
mutations: {
  addCounter (state) {
    state.counter ++
  },
  addCounter (state, payload) {
    state.counter += payload.value
  }
}

通过 commit 通知状态变化

store.commit('addCounter')
store.commit('addCounter', {value: 1})

Action

类似于mutation,不同在于

  • 只能通过 commit mutation 通知状态变化
  • mutation 只能包含同步操作,而 action 可以包含异步操作(比如, 在这里可以执行ajax请求)
actions: {
  askPermission ({commit}) {
    axios.get('/url').then((res) => {
      if(res.data.permission)
        commit('addCounter')
    }).catch((err) => {
      console.log('Error: in process "Ask permission".\n Detailed: ' + err)
    })
  },
  askPermission ({commit}, payload) {
    axios.get('/url', { params:payload }).then((res) => {
      if(res.data.permission)
        commit('addCounter')
    }).catch((err) => {
      console.log('Error: in process "Ask permission".\n Detailed: ' + err)
    })
  }
}

通过 dispatch 通知状态变化

store.dispatch('askPermission')
store.dispatch('askPermission', { author: "lonelydawn" })

Module

Vuex 允许我们将store分割成模块,每个模块拥有自己的state, mutation, action, getter, 甚至是嵌套子模块 :

const store = new Vuex.Store({
  modules: {
    a: {
      state: {},
      mutations: {
        addCounter(state) {}
      },
      actions: {},
      getters: {}
    },
    b: {
      namespaced: true, // 建立命名空间
      state: {},
      mutations: {
        addCounter(state) {}
      },
      actions: {}
    }
  }
})

store.state.a
store.state.b

//  提交 给 模块 a 的 mutations
store.commit('addCounter')
//  提交 给 模块 b 的 mutations
store.commit('b/addCounter')

最后

 Vuex 的基本用法已经介绍完了。

相关内容 :

官方文档: https://vuex.vuejs.org/zh-cn/

官方实例:  https://github.com/vuejs/vuex/tree/dev/examples

在下列内容中, 我将 演示如何使用 vue + vuex 以及其他常用组件从入门到实战。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Android 开发者

满足 Google Play 目标 API 等级 (targetSdkLevel) 的要求

50630
来自专栏FreeBuf

伽利略远程监控系统完全安装指南

7月初,外媒用臭名昭著形容意大利的网络军火商公司hacking team及其被黑事件,黑吃黑的黑客将该公司rcs系统的安装程序、源代码和邮件打包供所有人下载,更...

417100
来自专栏進无尽的文章

基础篇-iOS后台运行以及相关

对于APP的前后台运行情况的了解,有助于我们在实际开发中规避一些问题,以及采取稳妥的方法处理和解决问题,是很必须的。

70510
来自专栏hotqin888的专栏

电子规范管理系统(2)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/det...

18310
来自专栏Timhbw博客

【iOS秘籍】-下载历史版本App超详细教程

2016-12-0200:47:37 发表评论 5,804℃热度 1.软件准备 2.正式开始 3.安装旧版本App 4.总结 目录 有些时候我们需要下...

47270
来自专栏软件

测试人员的“偷懒大法”

(文 松心耐雪作品) 偷懒大法 测试一项重复而又累的工作,我想作为一个测试人员应该都是深有体会的,那么如何给自己减负呢?那就要学会“偷懒”。对测试来说繁杂的事情...

22650
来自专栏進无尽的文章

扒虫篇-一次被AppStore多次拒绝的经历和常见被拒原因(持续更新)

最近项目要上线了,可是因为用到了后台模式,一直被拒,(其中还包含了其他原因的被拒),所以打算纪录一下,希望能帮到有同样问题的朋友,也对常见被AppStore拒绝...

18420
来自专栏沃趣科技

Oracle 12c数据库优化器统计信息收集的最佳实践(三)|何时不需要收集统计信息

原文链接 http://www.oracle.com/technetwork/database/bi-datawarehousing/twp-bp-for-st...

33750
来自专栏互联网杂技

从输入URL到页面加载完的过程中都发生了什么事情

一个HTTP请求的过程 为了简化我们先从一个HTTP请求开始,简要介绍一下一个HTTP求情的网络传输过程,也就是所谓的“从输入 URL 到页面下载完的过程中都发...

372100
来自专栏北京马哥教育

推荐!国外程序员整理的系统管理员资源大全(一)

备份软件 Amanda -客户端-服务器模型备份工具 Bacula - 另一个客户端-服务器模型备份工具 Backupninja -轻量级,可扩展的元数据备份系...

574100

扫码关注云+社区

领取腾讯云代金券