网站首页 > 技术文章 正文
1.前言
官网地址:https://vuex.vuejs.org/zh/
官网介绍:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
作用: 将整个系统中所有的状态(需要跨页面 跨组件传值的变量)都存储到vuex仓库中,实现任意组件都可以对该数据进行存取操作。
2.vue 组件传值回顾
- 父传子 动态属性+props
- 子传父 $emit+自定义事件
- 中央事件总线 Vue.prototype.$bus=new Vue() +$emit+$on
- 祖宗孙子传值: provide+ inject
2.1 父传子 动态属性+props
父组件
<子组件名 title="你好啊" :age="20"></子组件名>
子组件
通过props 接收后, 直接用 this.变量使用
props:{
title:{
type:String,
default:'标题'
},
age:{
type:Number,
default:0
},
}
2.2 子传父 $emit+自定义事件
父组件
<子组件名 @自定义事件类型名="执行函数"></子组件名>
methods:{
执行函数(data){
//data 就是 子组件传递给父组件的数据
}
}
子组件
this.$emit('自定义事件类型名',传递的数据)
2.3 中央事件总线 $bus eventBus
在同一个页面组件中 的所有子组件可以任意传递数据
main.js 全局挂载 一个新的vue实例对象作为 中央
Vue.prototype.$bus = new Vue()
发送数据的组件
//发送数据
this.$bus.$emit('自定义事件类型',发送的数据)
接收数据的组件
接收数据的组件可以在created 生命周期中 监听该自定义事件,如果被触发就可以拿到数据
this.$bus.$on('自定义事件类型',(data)=>{
//data 就是 拿到的数据
})
2.4 祖宗孙子传值: provide+ inject
优:祖宗节点定义好数据,所有的孙子组件 都可以使用该数据 非常方便
缺:只能传递一个 固定值下去,没有响应式(子组件修改了该数据,祖宗节点的数据并不会发生变化)
祖宗组件
// 祖宗注入依赖
provide: {
name: '你好呀',
},
// 祖宗注入依赖
provide() {
return {
name: "你好呀",
};
},
孙子组件
export default {
inject:['name'],
mounted(){
//可以获取和使用
console.log(this.name);
//不能修改---报错
this.name = '我是孙子组件'
}
}
2.5 中间商:父亲组件带动态属性 $attrs $listeners
通过属性传值:可以快速实现 祖宗==>孙子 孙子==>祖宗【父亲组件只是一个中间商 负责 转发数据和转发事件】
爷爷组件
<template>
<div>
我是爷爷组件
<button @click="title='我是爷爷组件的新数据'">点击修改数据</button>
<hr />
<father :title="title" @change="getData"></father>
</div>
</template>
<script>
import Father from './components/AppFather.vue'
export default {
data() {
return {
title: "我是爷爷组件的数据",
};
},
methods:{
//根据自定义数据 获取孙子组件的传递数据
getData(data){
console.log(data);
}
},
components: {
Father,
},
};
</script>
父亲组件
父亲组件 通过$attrs 将获取到的上一层的数据 传递给 下一级
父亲组件 通过 $listeners 将获取到的自定义事件 传递给上一级 触发
<template>
<div>
父亲组件:
<hr>
<grand-son v-bind="$attrs" v-on="$listeners" ></grand-son>
</div>
</template>
<script>
import GrandSon from './GrandSon.vue'
export default {
components:{
GrandSon
}
}
</script>
孙子组件
<template>
<div>
我是孙子组件:
<p>{{ title }}</p>
<button @click="changeData">回传数据给祖宗</button>
</div>
</template>
<script>
export default {
props: {
// 在爷爷组件中传递过来的属性
title: {
type:String,
default:'标题'
},
},
methods:{
changeData(){
let data ={msg:"我是孙子组件回传的数据"}
this.$emit('change',data)
}
},
3.Vuex 状态管理仓库
- 安装vuex
yarn add vuex@3.6.2
//或
npm i vuex@3.6.2
- 创建vuex 的仓库文件 src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
//注册插件
Vue.use(Vuex);
//根据vuex的store 生成实例对象
const store = new Vuex.Store({
//存数据的仓库
state:{
name:'comentang'
},
//修改仓库中数据的同步方法
mutations:{
},
//调用 同步方法 实现异步修改仓库中的数据
actions:{
}
})
//暴露生成的vuex实例
export default store;
- main.js 进行导入和挂载
import store from './store'
new Vue({
router,
store, //将store 实例挂载到vue顶级实例对象上
render: h => h(App)
}).$mount('#app')
4 获取 state 中的数据
state:{
name:"cometnag"
}
- 直接通过实例对象层级查找
缺点:每次改变都需要使用该语句进行重新获取,代码太冗长
this.name = this.$store.state.name //cometang
- 通过 计算属性 获取值
优点:如果仓库中的数据发生了变化,computed 会自动触发,重新更新值
computed:{
nameData(){
return this.$store.state.name;
}
}
- 通过计算属性 + 对象解构获取
将mapState 对象解构出来直接放到 computed中
优点:使用简便,推荐此方法
import {mapState} from 'vuex'
computed:{
...mapState(['name'])
}
5.mutations 修改数据的方法
5.1 在组件中直接修改值
直接通过实例对象层级赋值
缺点:任何组件任何时候都可以修改这个数据,给数据维护带来了不稳定性。
vuex官网页非常明确的指出,修改vuex仓库中的数据必须使用 vuex中定义的方法。
低版本的vuex 数据会修改成功 但是控制台会有报错提示。
this.$store.state.name = '新数据'
5.2 定义mutations的方法 用来修改数据
const store = new Vuex.Store({
//存数据的仓库
state:{
name:'comentang'
},
//修改仓库中数据的同步方法
mutations:{
changeName(state,newData){
state.name = newData
}
},
})
- 在组件中 调用该方法 实现修改数据
this.$store.commit('changeName',新数据)
- methods+解构的方式 【推荐】
import { mapMutations } from 'vuex';
methods:{
// 注意,mapMutations是解构到methods里面的,而不是计算属性了
...mapMutations(['changeName']),
//使用方法和methods中的函数 一致。
// this.changeName(新数据) 修改数据
}
6. actions 异步修改数据
定义actions 异步操作中 通过上下文 调用同步方法 修改数据
//调用 同步方法 实现异步修改仓库中的数据
actions:{
//1s之后 通过上下文 调用同步方法修改数据
setAsyncData(context,newData){
return new Promise(resolve=>{
setTimeout(()=>{
context.commit('changeName',newData);
resolve();
},1000)
})
}
}
- 在组件中 调用该方法 实现修改数据
let res = await this.$store.dispatch('setAsyncData',this.title)
- methods+解构的方式 【推荐】
import { mapActions } from 'vuex';
methods:{
// 注意,mapActions是解构到methods里面的,而不是计算属性了
...mapActions(['setAsyncData']),
let res= await this.setAsyncData(this.title)
}
7.修饰器:Getters
获取数据时 统一对该数据进行处理之后 再返回新数据
特点:必须要有return 返回新数据 ,调用时不需要传参数
定义修饰器
getters:{
updateName(state){
return '你好呀'+state.name;
}
}
- 组件中直接使用 获取数据
this.$store.getters.updateName
- 通过computed 解构函数使用
import {mapGetters} from 'vuex'
computed:{
...mapGetters(['updateName'])
},
created() {
//取值
this.updateName1 = this.updateName
}
8. 模块 Module
假设一个项目功能比较复杂,在vuex中存储的数据非常多,设置出现了同名的情况,这种时候就不能直接写到一个store 文件中了,应该根据不同的功能模块 对 该store文件进行拆分。
思路:写独立的js文件 将 5个核心配置写入一个对象 并 暴露出去,导入到总的store里面的modules里面
现有模块: 用户模块users 商品模块 goods
src/store/index.js #总的vuex主模块
src/store/users.js #用户模块
src/store/goods.js #商品模块
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
// 导入子模块
import users from './users'
import goods from './goods'
//注册插件
Vue.use(Vuex);
//根据vue的store 生成实例对象
const store = new Vuex.Store({
state: {
name: '我是主模块的cometang'
},
mutations: {
},
actions: {
},
getters: {
},
//模块
modules: {
users, goods
}
})
//暴露生成的vuex实例
export default store;
// goods
const goods = {
namespaced: true,
state:{
goodsName:'我是goods的name'
},
mutations:{
},
actions:{
},
getters:{
}
}
export default goods
//users
const users = {
namespaced: true,
state: {
userName: '我是userjs的name'
},
mutations: {
},
actions: {
},
getters: {
}
}
export default users
注意:使用了模块化和命名空间之后对于子模块中的数据,方法的调用 不再建议使用 解构赋值快速复制的方式进行.
原因:本来命名空间打开就是为了区分各个不同的模块,如果用解构的方式,可能会造成数据变量名 方法名重名使用的风险。
- 使用方式
//获取数据
this.$store.state.users.userName;
//获取Getters 修饰器的数据
this.$store.getters.users.userName;
//调用同步方法
this.$store.commit('模块名/mutations的方法名',传递的数据)
// 调用异步方法
this.$store.dispatch('模块名/actions的方法名',传递的数据)
- 解构使用
特点:一个组件中 只能解构一个模块的数据 和方法
import { mapState,mapMutations,mapActions,mapGetters } from 'vuex';
computed:{
...mapState('users',['userName']), //this.userName
...mapGetters('users',['newUserName']) //this.newUserName
},
methods:{
...mapMutations('users',['updateName']), //this.updateName(数据)
...mapActions('users',['asyncUpdateName'])//this.asyncUpdateName(数据)
},
9.Vuex 数据持久化 插件
系统中经常需要将很多数据 存储起来 以后仍然可以使用(关闭浏览器之后 重新打开仍然可用)
思路一: 在所有的state 中 增加循环,把数据全部存储到本地存储localStorage之中。
思路二:使用数据持久化的插件
npm install vuex-persistedstate
或
yarn add vuex-persistedstate
//数据持久化插件导入
import persistedState from 'vuex-persistedstate'
//根据vue的store 生成实例对象
const store = new Vuex.Store({
state: {
},
mutations: {
},
actions: {
},
getters: {
},
//模块
modules: {
},
plugins: [persistedState()] //添加插件
})
//暴露生成的vuex实例
export default store;
猜你喜欢
- 2024-09-22 35《Vue 入门教程》Vue-Cli 项目文件结构分析
- 2024-09-22 vuex基础进阶用法(module模块化)
- 2024-09-22 Vue入门025- 求和案例_vuex版(getters的使用)
- 2024-09-22 Vue实战——vue-cli3创建项目是怎么集成vuex状态管理的?
- 2024-09-22 挑战全网最幽默的Vuex系列教程:第六讲 Vuex的管理员Module实战
- 2024-09-22 万字总结Vue(包含全家桶),希望这一篇可以帮到您(二)
- 2024-09-22 Vue开发库存管理前端页面时一些小经验记录
- 2024-09-22 基于 Vue 技术栈的微前端方案实践
- 2024-09-22 Vue(Axios+VueRouter+Vuex)的入门使用
- 2024-09-22 「Vuex入门」核心概念1.State
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)