Vue知识点整理(五)- vuex(1)- Vuex简介、Vuex工作原理、搭载Vuex环境、求和案例
一、vuex简介1.1 vuex是什么概念:专门在Vue中实现集中实状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式管理(读/写),也是一中组件间通信的方式,且适用于任意组件间通信vuex1.2 什么时候使用Vuex多个组件依赖同一状态来自不同组件的行为需要变更同一状态二、Vuex工作原理图2.1 官方vuex工作原理图每一个 Vuex 应用的核心就是 store,里面
目录
一、vuex简介
1.1 vuex是什么
概念:专门在Vue中实现集中状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式管理(读/写),也是一中组件间通信的方式,且适用于任意组件间通信
1.2 什么时候使用Vuex
- 多个组件依赖同一状态
- 来自不同组件的行为需要变更同一状态
二、Vuex工作原理图
2.1 官方vuex工作原理图
每一个 Vuex 应用的核心就是 store,里面又包括:
1. State(状态):用于数据的存储(对象类型数据),是store中唯一数据源
2. Actions(行为):类似于mutation,用于提交mutation来改变状态,而不直接变更状态,可以包含任意异步事件
3. Mutations(转变):类似函数,改变state数据的唯一途径,且不能用于处理异步事件。
Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方
4. Getter(数据加工):如vue中的计算属性一样,基于state数据的二次包装,常用于数据的筛选和多个数据的相关计算
5. Module:类似于命名空间,用于项目中将各个模块的状态分开定义和操作,便于维护
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。
2.2 Vuex工作流程
(1) vc(vue组件)通过调用 store 中 dispatch方法,派发给actions执行,actions可以继续通过调用dispatch方法给自身派发另一个actions,也可以调用异步方法(Backend API)
(对应原理图:Vue Components -> Dispatch -> Acitons)
(2)acitons调用 store 中的 commit方法,由 actions 提交一个 mutation
(对应原理图:Actions -> Commit -> Mutation)
如果vc(vue组件)与 actions 之间没有业务逻辑,也可以直接由vc(vue组件)提交一个 mutation
(即Vue Components -> Commit -> Mutation)
(3)mutations去更新state中的数据,不需要手动执行(Mutate 不是一个API,不用去调用),由mutations的回调函数内对应的代码片段自动执行(执行后底层自动走Mutate)。
一般是由mutations更新state中的数据,在此处可以被开发者工具(Devtools)直接监控
(对应原理图:Mutation -> Mutate -> State)
因为actions.context中也包含了state,可由actions去更新state中的数据,不经过mutation,因而不被开发者工具(Devtools)监控,但不提倡这么做
(即Actions -> Mutate -> State)
(4)state中的数据更新之后,就会通知vue进行渲染
(对应原理图:State -> Render -> Vue Components)
组件中读取vuex中的数据:
$store.state.自定义的数据名 // 在vuex中index.js文件中state内定义的数据
组件中修改vuex中的数据:
$store.dispath('action中的方法名',数据)
或
$store.commit('mutation中的方法名',数据)
注意:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit
三、搭建Vuex环境
3.1 安装
终端安装
npm i vuex
注意:
- 2022.2.7,vue3称为了默认版本,即在终端执行 npm i vue,默认安装的是vue3版本,而vuex也更新到4版本,所以 终端执行 npm i vuex 默认安装的是vuex4
- vuex4 只能在 vue3中使用,而vue2中,要用的是vuex的3版本
所以如果用的是vue2的话,则需要安装vuex的3版本,在终端执行:
npm i vuex@3
3.2 引用Vuex
1. 创建文件:src/store/index.js
// 引入Vue核心库
import Vue from "vue";
// 引入Vuex
import Vuex from "vuex";
// 应用Vuex插件
Vue.use(Vuex);
// 准备actions对象 - 响应组件中用户的动作
const actions = {};
// 准备mutations对象 - 修改state中的数据
const mutations = {};
// 准备state对象 - 保存具体数据
const states = {};
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
});
2. 在main.js中创建vm时传入store配置项
// 引入Vue
import Vue from "vue";
// 引入App
import App from "./App.vue";
// 引入store配置项
import store from "./store";
Vue.config.productionTip = false;
// 创建vm
new Vue({
el: "#app",
render: (h) => h(App),
store,
// 安装全局事件总线
beforeCreate() {
Vue.prototype.$bus = this;
},
});
如何验证是否成功引入store配置项?即可控制台输出组件实例对象,找到$store即为成功引入
注意:至于为何引入Vuex是在 src/store/index.js 中引入,而非在 main.js 中直接引入使用
- 因为 import 引入模块或者文件,在执行时,默认是放在文件最前端优先执行的。而当我们在main.js中引入store配置项时,先决条件是需要 Vue.use(Vuex) 之后执行,因此在 main.js 中直接引入使用Vuex 和 store配置项时,就会出现报错
例如,如下main.js代码,便会出现报错
// 错误示范案例
// 引入Vue
import Vue from "vue";
// 引入App
import App from "./App.vue";
// 引入Vuex
import Vuex from "vuex";
// 应用Vuex插件
Vue.use(Vuex);
// 引入store配置项
import store from "./store";
Vue.config.productionTip = false;
// 创建vm
new Vue({
el: "#app",
render: (h) => h(App),
store,
// 安装全局事件总线
beforeCreate() {
Vue.prototype.$bus = this;
},
});
由图示可看出错误提示信息,vuex 在创建 store实例 之前必须先调用 Vue.use(Vuex)
四、案例练习 - 求和案例
4.1 Count.vue
Count子组件:包含4个按钮的点击事件
<template>
<div style="padding: 20px">
<h1>当前求和为:{{ $store.state.sum }}</h1>
<select v-model="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前求和为奇数再加</button>
<button @click="incrementWait">等1s后再加</button>
</div>
</template>
<script>
export default {
name: "Count",
data() {
return {
n: 1, // 用户选择的数字
};
},
methods: {
increment() {
this.$store.commit("ADD", this.n);
},
decrement() {
this.$store.commit("SUB", this.n);
},
incrementOdd() {
this.$store.dispatch("addOdd", this.n);
},
incrementWait() {
this.$store.dispatch("addWait", this.n);
},
},
};
</script>
<style></style>
4.2 App.vue
引入Count组件作为子组件,并使用Count组件标签
<template>
<div>
<Count></Count>
</div>
</template>
<script>
import Count from "./components/Count.vue";
export default {
name: "App",
components: { Count },
};
</script>
<style></style>
4.3 index.js
store配置,准备了actions、mutations、state
// 引入Vue核心库
import Vue from "vue";
// 引入Vuex
import Vuex from "vuex";
// 应用Vuex插件
Vue.use(Vuex);
// 准备actions对象 - 响应组件中用户的动作
const actions = {
add(context, value) {
context.commit("ADD", value);
},
sub(context, value) {
context.commit("SUB", value);
},
addOdd(context, value) {
if (context.state.sum % 2) {
context.commit("ADD", value);
}
},
addWait(context, value) {
setTimeout(() => {
context.commit("ADD", value);
}, 1000);
},
};
// 准备mutations对象 - 修改state中的数据
const mutations = {
ADD(state, value) {
state.sum += value;
},
SUB(state, value) {
state.sum -= value;
},
};
// 准备state对象 - 保存具体数据
const state = {
sum: 0,
};
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
});
更多推荐
所有评论(0)