# 数据共享
我们在学习 vue 的时候,可以知道要想实现数据间的数据共享,常见的有下面的几种方式:
- props 属性绑定
- 自定义事件
- 全局事件总线
但我们发现:当开发大型单页面应用时,我们需要大范围、频繁的使用数据共享,上述的方案显然就力不从心了。
# 一、状态管理模式
下面看看,在 vue 中的状态管理方案,
- 单向数据流:就是我们从接触 vue 到现在采取的方案
- 全局单例模式管理:vuex 的一种新的解决方案
# 1、单向数据流
示意图:
![](https://blog-cloudbed.oss-cn-chengdu.aliyuncs.com/note-taking/20220709151119.png)
流程体验(代码)
new Vue({
// state
data() {
return {
count: 0
}
},
// view
template: `
<div>{{ count }}</div>
`,
// actions
methods: {
increment() {
this.count++
}
}
})
缺点:
答案
当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏
- 多个视图依赖于同一状态
- 来自不同视图的行为需要变更同一状态
虽然这些在视图较少的情况下,我们可以用前面的知识解决,但相关联的视图一旦多起来,那将变得不可维护。
# 2、全局单例模式 ✨
为了解决上面单向数据流存在的问题,vue 官方设计例专门的状态管理库 Vuex。
它把组件的共享状态抽取出来,以一个全局单例模式管理
提示
Vuex 使用单一状态树(SSOT),整个应用仅仅包含一个 store 实例(在 Pinia 中没有 Module,可以创建多个 store 实例),但它可以利用 Module 创建多个模块
示意图:
![](https://blog-cloudbed.oss-cn-chengdu.aliyuncs.com/note-taking/20220709151441.png)
提示
重点关注 vue 组件使用 Mutations 的两条路线
直接触发,或者通过 Actions 触发
还要理解,State
和 Actions、Mutation
间的本质区别
前者作为 computed,后者作为 methods
流程体验 ✍(代码)
- store/index.js
const actions = {
// up: ({ commit }) => commit('UP'),
// down: ({ commit }) => commit('DOWN'),
upIfOdd({ commit, state }) {
if ((state.count + 1) % 2 === 0) {
commit('UP')
}
},
upAsync({ commit }) {
return new Promise((resolve) => {
setTimeout(() => {
commit('UP')
resolve()
}, 2000)
})
}
}
const mutations = {
UP(state) {
state.count++
},
DOWN(state) {
state.count--
}
}
const state = {
count: 0
}
- 组件
<template>
<div class="home">
<h3>AboutWorld组件内容</h3>
数字: {{ $store.state.count }}
<br />
数字: {{ count }}
<br /><br />
<button @click="upIfOdd">奇数时--> +1</button>
<button @click="upAsync">延迟2秒--> +1</button>
<br /><br />
<button @click="UP">+1</button>
<button @click="DOWN">-1</button>
</div>
</template>
<script>
import { mapActions, mapMutations, mapState } from 'vuex'
export default {
name: 'AboutWorld',
computed: {
...mapState(['count'])
},
methods: {
...mapActions(['up', 'down', 'upIfOdd', 'upAsync']),
...mapMutations(['UP', 'DOWN'])
}
}
</script>
官方案例:https://github.com/vuejs/vuex/tree/3.x/examples
提示
Actions 就像一个餐厅服务员,小饭店不一定需要它。但是大饭店得需要他去做一些业务处理:客人订单管理(js 逻辑处理),通知饮料/蔬菜采购(Backend API)等
像 Actions
、Mutations
、State
等都是一个对象,它们由背后的大佬 store 操控着。示意图上是从宏观的角度看的(即 vue 组件 和 vuex 之间的关系)
什么时候,什么数据要使用全局单例模式管理
答案
当我们确定某些数据,可能会在多个视图中交叉使用的时候,我们就可以将这些数据放在 vuex 中。官方的说法就是:
- 多个视图依赖于同一状态
- 来自不同视图的行为需要变更同一状态
# 二、Vuex
# 1、简介
官方介绍:
Vuex (opens new window) 可以帮助我们管理共享状态(数据),并附带了更多的概念和框架。
概念:
简单的来说,就是 Vuex 是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享。
效果演示:
![](https://blog-cloudbed.oss-cn-chengdu.aliyuncs.com/note-taking/20220608204642.png)
使用范围 ✨:
一般情况下,存储到 vuex 中的数据是组件间的共享数据;对于组件中私有数据,存储在组件自身的 data 中即可。
# 2、安装使用
# ① 安装
npm install vuex@3
每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。
# ② 构建 store
- store / index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex) // 插件注册成功(vue中能使用vuex了)
const actions = {}
const mutations = {}
const state = {}
// 大佬store产生了✍
export default new Vuex.Store({
actions,
mutations,
state
})
# ③ 使用 vuex
- 局部使用
<script>
import store from '../store/index'
export default {
name: 'HomeView',
created() {
store.commit('increment')
// 效果:
console.log(store.state.count)
}
}
</script>
- 全局使用
// main.js
import store from './store/index'
new Vue({
store, // store: store的简写
render: (h) => h(App)
}).$mount('#app')
<script>
export default {
name: 'AboutWorld',
created() {
this.$store.commit('increment')
// 效果:
console.log(this.$store.state.count)
}
}
</script>
# 3、脚手架
同创建 vue-router 路由一样,使用 vue-cli 创建 SPA 项目以后,会自动生成相关文件 😂,不用自己手动编写。
注意的是:在 vue-cli <= 2.x 的旧版本模板时,是没法一键配置 Vuex 的。