Vuex实现数据共享的方法


Posted in Javascript onDecember 20, 2019

在用vue作为前端框架进行开发的时候,对于组件间的传值你一定不会陌生,如果只是简单的父子组件传值,我想你肯定不会选择用Vuex来进行状态管理,但是如果你需要构建一个中大型单页应用,组件间数据交互比较复杂频繁,你很可能会考虑如何更好地在组件外部管理状态,那么Vuex 将会成为自然而然的选择。

Vuex 是什么?

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

用个人的话总结下: Vuex就是为了实现多组件数据共享,从而建立一个叫store的数据管理库,将需要共享的数据存放在里面,在需要的地方可以取出来作为初始数据,也可以在组件内通过dispatch或者提交commit方法来改变该原始数据状态,从而实现的data的共享。

Vuex的核心

1、 State

Vuex中的数据源,我们需要保存的数据就保存在这里,可以在页面通过this.$store.state来获取我们定义的数据。

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const state = {
 number: 0
}

export default new Vuex.Store({
 state,
});

在页面中通过this.$store.state.number 即可获取到当前的值。

2、Getter

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

Getter 接受 state 作为其第一个参数:

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const state = {
 number: 0
}

const getters = {
 getNumber(state) {
  return state.number + 1
 }
}
export default new Vuex.Store({
 state,
 getters,
});

在页面你可以用两种方式取到getters里面的值

1、通过属性访问

Getter 会暴露为 store.getters 对象,你可以以属性的形式访问这些值 如: this.$store.getters.getNumber

Getter 也可以接受其他 getter 作为第二个参数:

const state = {
 number: 1
}

const getters = {
 getNumber(state) {
  return state.number + 1 // 2
 },
 getDoubNUmber(state, getters) {
  return state.number + getters.getNumber // 3
 }
}

注意: getter 在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的。

2、 通过方法访问

你也可以通过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时非常有用。

const state = {
 number: 1,
 list: [1, 2, 3, 4, 5]
}

const getters = {
 getNumber(state) {
  return state.number + 1 // 2
 },
 getDoubNumber(state, getters) {
  return state.number + getters.getNumber // 3
 },
 filterNumber:(state)=>(num)=> {
  return state.list.find(item=> item%num === 0)
 } 
}
export default new Vuex.Store({
 state,
 getters,
});

注意, getter 在通过方法访问时,每次都会去进行调用,而不会缓存结果 this.$store.getters.filterNumber(3)

3、Mutation

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方, 并且它会接受 state 作为第一个参数 , 提交载荷(payload) 作为额外的参数 ,并且在大多数情况下,载荷应该是一个对象,这样可以包含多个字段并且使记录的 mutation 会更易读:

你可以这样写:

const mutations = {
 increment(state, n) {
 state.number += n
 }
}

但你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

this.$store.commit('increment', 1)

也可以这样写:

const mutations = {
 increment(state, payload) {
 state.number += payload.count
 }
}

然后:

使用 this.$store.commit('increment', {count: 1})  提交,

// 或者另一种方式是直接使用包含 type 属性的对象进行提交:
this.$store.commit({
 type: 'increment',
 count: 1
})

特别说明:在 Vuex 中,mutation 都是同步任务:为了处理异步操作,让我们来看一看 Action。

4、 Action

Action 类似于 mutation,不同在于:

1、Action 提交的是 mutation,而不是直接变更状态。

2、Action 可以包含任意异步操作。

虽然在页面中通过提交commit是可以达到修改store中状态值的目的,但是官方并不建议我们这样做,而是让我们去提交一个action,在action中提交mutation再去修改状态值。

const mutations = {
 increment(state) {
 state.number += 1
 }
}
const actions = {
 addNumber(context){
  context.commit('increment')
 }
}

Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters

addNumber( {commit} ){
 commit('increment')
}

以上这种写法等同于:

addNumber(context){
 context.commit('increment')
}

Action 通过 store.dispatch 方法触发:

this.$store.dispatch('addNumber')

同mutation 一样你也可以在action的时候传递参数

const mutations = {
 increment(state, number) {
 state.number += number
 }
}
const actions = {
 addNumber(context, number){
  context.commit('increment', number)
 }
 或者:
 addNumber( {commit}, number){
  commit('increment', number)
 }
}

触发方法: this.$store.dispatch('addNumber', 10)

关于在action 处理异步操作可以看下面这个例子:

const actions = {
 getData({commit}) {
  return new Promise((resolve, reject)=> {
   setTimeout(()=>{
   commit('getList')
   resolve()
   }, 1000)
  })
 }
}

然后再

this.$store.dispatch('getData').then(() => {
 // ...
})

完整 实例:

import Vue from "vue";
import Vuex from "vuex";
import { resolve, reject } from "any-promise";
Vue.use(Vuex);
const state = {
 number: 1,
 list: [1, 2, 3, 4, 5]
}
const getters = {
 getNumber(state) {
  return state.number + 1 // 2
 },
 getDoubNumber(state, getters) {
  return state.number + getters.getNumber // 3
 },
 filterNumber:(state)=>(num)=> {
  return state.list.find(item=> item%num === 0)
 } 
}
const mutations = {
 increment(state, n) {
 state.number += n
 },
 getList(state) {
 state.list = state.list.forEach((item)=> item*2)
 }
}
const actions = {
 addNumber( {commit} , n){
  commit('increment', n)
 },
 getData({commit}) {
  return new Promise((resolve, reject)=> {
   setTimeout(()=>{
   commit('getList')
   resolve()
   }, 1000)
  })
 }
}
export default new Vuex.Store({
 state,
 getters,
 mutations,
 actions
});

关于 Vuex中mapState、mapGetters、mapMutations、mapActions的用法

要用 首先得引入:

import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';

这玩意儿其实就是Vuex 内置的辅助函数,方便我们获取store里面的数据和方法

computed: {
 ...mapState([
 'number'
 ])
}
// 使用对象展开运算符将 getter 混入 computed 对象中
computed: {
 ...mapGetters([
  'getNumber',
  'getDoubNumber',
  // ...
 ])
} 
methods: {
 ...mapMutations([
  'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
 ...mapMutations({
  add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
 })
} 
methods: {
 ...mapActions([
  'addNumber', // 将 `this.addNumber()` 映射为 `this.$store.dispatch('addNumber')`
  // `mapActions` 也支持载荷:
  'addNumber' // 将 `this.addNumber(amount)` 映射为 `this.$store.dispatch('addNumber', amount)`
 ]),
 ...mapActions({
  requestData: 'getData' // 将 `this.requestData()` 映射为 `this.$store.dispatch('getData')`
 })
 }

以上是对Vuex实现状态管理的一个整个过程的理解,参考官方文档,然后自己写一遍,比较容易明白其中的道理,后面有时间想写React里面关于Redux实现状态管理的一个过程,对比其中,其实他们思想差不多, 只不过redux实现过程更多点,敬请期待!

Javascript 相关文章推荐
JavaScript 语法集锦 脚本之家基础推荐
Nov 15 Javascript
JavaScript中Math对象方法使用概述
Jan 02 Javascript
用简洁的jQuery方法toggleClass实现隔行换色
Oct 22 Javascript
js实现当复选框选择匿名登录时隐藏登录框效果
Aug 14 Javascript
举例讲解如何判断JavaScript中对象的类型
Apr 22 Javascript
深入理解JavaScript中的对象复制(Object Clone)
May 18 Javascript
H5用户注册表单页 注册模态框!
Sep 17 Javascript
Angular事件之不同组件间传递数据的方法
Nov 15 Javascript
详解VS Code使用之Vue工程配置format代码格式化
Mar 20 Javascript
跟混乱的页面弹窗说再见
Apr 11 Javascript
详解在HTTPS 项目中使用百度地图 API
Apr 26 Javascript
微信小程序 (地址选择1)--选取搜索地点并显示效果
Dec 17 Javascript
React 实现车牌键盘的示例代码
Dec 20 #Javascript
jquery实现商品sku多属性选择功能(商品详情页)
Dec 20 #jQuery
JavaScript实现简单计算器功能
Dec 19 #Javascript
微信小程序跨页面数据传递事件响应实现过程解析
Dec 19 #Javascript
js通过循环多张图片实现动画效果
Dec 19 #Javascript
JS实现水平移动与垂直移动动画
Dec 19 #Javascript
5分钟快速看懂ES6中的反射与代理
Dec 19 #Javascript
You might like
PHP图片上传代码
2013/11/04 PHP
php分页函数完整实例代码
2014/09/22 PHP
PHP之uniqid()函数用法
2014/11/03 PHP
PHP创建多级目录的两种方法
2016/10/28 PHP
PHP大文件切割上传功能实例分析
2019/07/01 PHP
游戏人文件夹程序 ver 3.0
2006/07/14 Javascript
web性能优化之javascript性能调优
2012/12/28 Javascript
jQuery的观察者模式详解
2014/12/22 Javascript
JavaScript字符串删除重复字符的方法
2015/12/25 Javascript
全面了解JS中的匿名函数
2016/06/29 Javascript
lhgcalendar时间插件限制只能选择三个月的实现方法
2017/07/03 Javascript
使用JavaScript根据图片获取条形码的方法
2017/07/04 Javascript
jQuery获取随机颜色的实例代码
2018/05/21 jQuery
JS实现十分钟倒计时代码实例
2018/10/18 Javascript
vue.js仿hover效果的实现方法示例
2019/01/28 Javascript
学习node.js 断言的使用详解
2019/03/18 Javascript
Vue中使用JsonView来展示Json树的实例代码
2020/11/16 Javascript
Python 绘图库 Matplotlib 入门教程
2018/04/19 Python
Pycharm设置去除显示的波浪线方法
2018/10/28 Python
解决pyinstaller打包pyqt5的问题
2019/01/08 Python
Python查找数组中数值和下标相等的元素示例【二分查找】
2019/02/13 Python
OpenCV HSV颜色识别及HSV基本颜色分量范围
2019/03/22 Python
六行python代码的爱心曲线详解
2019/05/17 Python
Python函数和模块的使用总结
2019/05/20 Python
Django 用户登陆访问限制实例 @login_required
2020/05/13 Python
Python如何实现远程方法调用
2020/08/07 Python
Hawes & Curtis官网:英国经典品牌
2019/07/27 全球购物
乡镇党委书记个人整改措施
2014/09/15 职场文书
2015年超市收银员工作总结
2015/04/25 职场文书
电影开国大典观后感
2015/06/04 职场文书
2019学校请假条格式及范文
2019/06/25 职场文书
创业计划书之废品回收
2019/09/26 职场文书
Python实现文本文件拆分写入到多个文本文件的方法
2021/04/18 Python
Python入门之基础语法详解
2021/05/11 Python
python数字转对应中文的方法总结
2021/08/02 Python
PostgreSQL常用字符串分割函数整理汇总
2022/07/07 PostgreSQL