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 相关文章推荐
js可突破windows弹退效果代码
Aug 09 Javascript
2012年开发人员的16款新鲜的jquery插件体验分享
Dec 28 Javascript
javascript匿名函数应用示例介绍
Mar 07 Javascript
JQuery实现级联下拉框效果实例讲解
Sep 17 Javascript
bootstrap学习笔记之初识bootstrap
Jun 21 Javascript
JS+CSS3模拟溢出滚动效果
Aug 12 Javascript
Angularjs实现mvvm式的选项卡示例代码
Sep 08 Javascript
Javascript中常用的检测方法小结
Oct 08 Javascript
JS中from 表单序列化提交的代码
Jan 20 Javascript
JavaScript动态检测密码强度原理及实现方法详解
Jun 11 Javascript
vue实现codemirror代码编辑器中的SQL代码格式化功能
Aug 27 Javascript
js实现中文实时时钟
Jan 15 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的一个完整SMTP类(解决邮件服务器需要验证时的问题)
2006/10/09 PHP
php在文件指定行中写入代码的方法
2012/05/23 PHP
一个PHP针对数字的加密解密类
2014/03/20 PHP
php下载文件源代码(强制任意文件格式下载)
2014/05/09 PHP
PHP使用逆波兰式计算工资的方法
2015/07/29 PHP
php实现支持中文的文件下载功能示例
2017/08/30 PHP
Laravel使用原生sql语句并调用的方法
2019/10/09 PHP
将函数的实际参数转换成数组的方法
2010/01/25 Javascript
jQuery1.4.2与老版本json格式兼容的解决方法
2011/02/12 Javascript
Extjs4 GridPanel的主要配置参数详细介绍
2013/04/18 Javascript
在表单提交前进行验证的几种方式整理
2013/07/31 Javascript
Mac/Windows下如何安装Node.js
2013/11/22 Javascript
关于Node.js中Buffer的一些你可能不知道的用法
2017/03/28 Javascript
jQuery实现动态生成表格并为行绑定单击变色动作的方法
2017/04/17 jQuery
VUE中v-model和v-for指令详解
2017/06/23 Javascript
Express系列之multer上传的使用
2017/10/27 Javascript
在React项目中使用Eslint代码检查工具及常见问题
2018/10/10 Javascript
Vue实现回到顶部和底部动画效果
2019/07/31 Javascript
Python自动登录126邮箱的方法
2015/07/10 Python
实例讲解Python编程中@property装饰器的用法
2016/06/20 Python
Python中的并发处理之asyncio包使用的详解
2018/04/03 Python
Python分割指定页数的pdf文件方法
2018/10/26 Python
Python3.6.x中内置函数总结及讲解
2019/02/22 Python
Python通过Manager方式实现多个无关联进程共享数据的实现
2019/11/07 Python
tensorflow的ckpt及pb模型持久化方式及转化详解
2020/02/12 Python
python七种方法判断字符串是否包含子串
2020/08/18 Python
Clarks鞋法国官方网站:英国其乐鞋品牌
2018/02/11 全球购物
墨尔本最受欢迎的复古风格品牌:Princess Highway
2018/12/21 全球购物
《一个中国孩子的呼声》教学反思
2014/02/12 职场文书
世博会口号
2014/06/20 职场文书
争先创优心得体会
2014/09/12 职场文书
房屋租赁授权委托书范本
2014/09/20 职场文书
2015年毕业实习工作总结
2015/05/29 职场文书
2019数学教师下学期工作总结
2019/06/27 职场文书
使用Oracle命令进行数据库备份与还原
2021/12/06 Oracle
MySQL中rank() over、dense_rank() over、row_number() over用法介绍
2022/03/23 MySQL