- 作者:老汪软件技巧
- 发表时间:2024-11-27 21:06
- 浏览量:
1.简介
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
在Vue 最重要就是 数据驱动 和 组件化,每个 组件都有自己 data ,template 和 methods, data是数据,我们也叫做状态,通过methods中方法改变 状态来更新视图,在单个组件中修改状态更新视图是很方便的,但是实际开发中是多个组件(还有多层组件嵌套)共享同一个状态时,这个时候传参就会很繁琐,我们这里就引进 Vuex 来进行状态管理,负责组件中的通信,方便维护代码。
一个简单的 Vue 计数应用开始:**
<template>
<div>
<div>{{cnt}}div>
<button @click="add">button>
div>
template>
<script>
export default {
name: 'Demo',
components: {},
data () {
return {
cnt:1
}
},
methods: {
add(){
this.cnt += 1
}
}
}
script>
<style lang='scss' scoped>
style>
但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
1、 多个视图依赖于同一状态。2、 来自不同视图的行为需要变更同一状态。
解决方案:
对于问题一,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
对于问题二,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此,我们要把组件的共享状态抽取出来,以一个全局单例模式管理?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
使用 Vuex 的好处:vuex的使用
/* src/store/index.js `*/`
// 导入 Vue
import Vue from 'vue'
// 导入 Vuex 插件
import Vuex from 'vuex'
// 把 Vuex 注册到Vue 上
Vue.use(Vuex)
export default new Vuex.Store({
// 状态 vuex的基本数据,用来存储变量
state: {
},
// 从基本数据(state)派生的数据,相当于state的计算属性,具有返回值的方法。 类似组件中的computed
getters:{},
// 用来处理状态
mutations: { },
// 用于异步处理
actions: {},
// 用来挂载模块
modules: {}
})
modules子模块
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module) 。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割.
例如:分模块形式管理数据,比如user模块管理用户信息数据,ledger模板管理台账本业务数据,baseParams模块管理项目全局通用的参数数据。
命名空间
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
如果希望你的模块具有更高的封装度和复用性,你可以通过添加namespaced: true的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
1.state
vuex的基本数据,用来存储变量
// state存储基本数据
state: {
name:''
age: ''
}
在Vue中使用
一般是在 computed获得Vuex的state
1、 在Vue中使用直接使用 this.$store.state.name
2、 mapState辅助函数
推荐推荐使用第二种这种写法。原因如下:
① 语法更加简洁明了,直接指定模块名和需要映射的属性名称,不需要额外的箭头函数或命名空间参数。
② 在组件中使用count时,可以清晰地知道该属性来自于哪个模块,提高了可读性。
③ 当需要映射多个属性时,可以在数组中列出所有需要映射的属性,使代码更加整洁。
<template>
<div id="app">
{{ name }}
{{ age }}
div>
template>
<script>
// 从 Vuex 中导入 mapState
import { mapState } from 'vuex'
export default {
name: 'App',
computed: {
//方法1 根模块下的引用
name(){
return this.$store.state.name
},
//方式2 将 store 映射到当前组件的计算属性 根模块下的引用
...mapState(['name', 'age']),
//方法1 子模块下的引用
name(){
return this.$store.state.user.name
},
//方式2 子模块下的引用
...mapState('user',['name', 'age'])
}
}
script>
<style scoped>
style>
2. getters
有时候我们需要从 store 中的 state 中派生出一些状态,例如对列表进行过滤并计数:
// getter
getters: {
userIdDouble: function(state){
return state.userId * 2
}
在Vue中使用
1、this.$store.getters.userIdDouble
2、 mapGetters辅助函数
// 从 Vuex 中导入 **mapGetters**
import { **mapGetters** } from 'vuex'
export default {
name: 'App',
computed: {
//方法1
name(){
return this.$store.getters.userIdDouble
},
//方式2
...mapGetters(['userIdDouble'])
}
}
3. mutations
提交更新数据的方法,必须是同步的(如果需要异步使用action)。提交mutation是更改Vuex中的store中的状态的唯一方法。
每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。(提交荷载在大多数情况下应该是一个对象),提交荷载也可以省略的。
// mutations
mutations: {
setUserInfo: (state, userId) => {
state.userId = userId
},
},
在Vue中使用
1、使用commit:同步操作
2、mapMutations辅助函数
import { mapMutations } from 'vuex'
export default {
//..
methods: {
//方式2 在其他方法中或tempt直接使用即可
...mapMutations(['setUserInfo']),
getUserInfo(){
const userInfo= {
name:'张三',
age:18
}
//方式1
this.$store.commit('setUserInfo', userInfo)
//方式2
this.setUserInfo(userInfo)
}
}
}
4. actions
和mutation的功能大致相同,不同之处在于 ==》
Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。Action 类似于 mutation,不同在于:Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。
// actions
actions: { // {} 是es6中解构,把对象解构成属性
login({ commit }, value) {
commit('setUserInfo', value)
},
}
在Vue中使用
1、dispatch:异步操作2、mapActions辅助函数
import { mapActions } from 'vuex'
export default {
//..
methods: {
...mapActions(['login']),
subimt(value){
// 方式1
this.$store.dispatch('login', value)
// 方式2
this.login(value)
}
}
}
总结
至此,可以简单总结一下辅助函数通过vuex的使用,比喻成映射关系为:
复习一下命名空间的写法:
mapXXXs('命名空间名称',['属性名1','属性名2'])
//重命名写法
mapXXXs('命名空间名称',{
'组件中的新名称1':'Vuex中的原名称1',
'组件中的新名称2':'Vuex中的原名称2',
})
vuex的另一种使用--- 动态注册方法 registerModule的实现
动态创建,就是在需要的地方,再去注册该模块。在页面中,使用如下方式进行手动注册,提供模块内部组件间的数据共享。
业务模块中基础使用
import customModule from './__sotre'
export default {
created() {
this.$store.registerModule('customModule', customModule)
},
beforeDestroy() {
this.$store.unregisterModule('customModule')
},
}