Vuex 状态管理
2022-03-08 本文已影响0人
丽__
- Vue组件间通信方式
- Vuex核心概念和基本使用
- 购物车案例
- 模拟实现vuex
一、组件内的状态管理流程
image.png- 状态管理组成
- state:驱动应用的数据源
- view:以声明方式将state映射到视图
- actions:响应在view上的用户输入导致的状态变化
二、组件间通信方式——父组件给子组件传值
- 子组件中通过props接收数据
- 父组件中给子组件通过相应属性传值
// 父组件
<child title='父组件'></child>
import child from 'child'
export default{
components:{
child
}
}
//子组件
prop:['title']
或
prop:{
title:String
}
三、组件间通信方式——子组件给父组件传值
//父组件
<child @enlargeText='enlargeText'></child>
<child @enlargeText='hFontSize += $event'></child>
import child from 'child'
export default{
components:{
child
},
methods:{
enlargeText(size){
console.log('子组件传过来的值为:'+size)
}
}
}
//子组件
<button @click="handler">点击文字切换大小</button>
handler(){
this.$emit('enlargeText',20)
}
四、组件间通信方式——不相关组件传值(bus)
// bus.js
import Vue from 'vue'
export detault new Vue()
// 01.vue
<div class="number" @click="sub"> - </div>
<input type="text" :value="value">
<div class="number" @click="add"> + </div>
import bus from 'bus.js'
export default{
props:{
num:Number
},
created(){
this.value = this.num
},
data(){
return {
value:-1
}
},
methods:{
sub(){
this.value--;
bus.$emit('numchange',this.value)
},
add(){
this.value++;
bus.$emit('numchange',this.value)
}
}
}
// 02.vue
<div>{{ msg }}</div>
import bus from 'bus.js'
export default{
data(){
return{
msg:''
}
},
created(){
bus.$on('numchange',(value)=>{
this.msg = `您选择了${value}件商品`
})
}
}
app.vue
<sibling01 :num='2'><sibling01>
<sibling02></sibling02>
五、组件间通信方式——通过ref获取子组件
- ref两个作用
- 在普通的HTML标签上使用ref,获取到的是DOM
- 在组件标签上使用ref,获取到的是组件实例
this.$refs.refsName
- 其他常见方式
- $root 不推荐
- $parent 不推荐
- $children 不推荐
- $refs
六、Vuex介绍
- Vuex是专门为Vue.js设计的状态管理库
- Vuex采用集中式的方式存储需要共享的状态
- Vuex的作用是进行状态管理,解决复杂组件通信,数据共享
- Vuex继承到了devtools中,提供了time-travel时光旅行历史回滚功能
- 什么情况下使用Vuex
- 非必要的情况下不要使用Vuex
- 大型的单页应用程序
- 多个视图依赖于同一状态
- 来自不同视图的行为需要变更同一状态
七、Vuex核心概念
- Store :是一个容器,包含着应用中的状态,不能直接改变Store状态,要通过提交mutation的方式改变状态
- State:状态,保存在Store中,因为Store是唯一的,所以State状态也是唯一的,称为单一状态树,所有的状态都保存在State中,会让程序难以维护,可以通过模块(module)解决。这里的状态是响应式的。
- Getter:就像是vue中的计算属性,方便从一个属性派生出其他的值,内部可以对计算的结果进行缓存,只有当依赖的状态发生改变的时候才会重新计算。
- Mutation:状态的变化要通过提交Mutation完成。
- Action:和Mutation类似,不同的是Action可以进行异步的操作,内部改变状态的时候,都需要提交Mutation。
-
Module:模块。由于使用的单一状态树,应用的所有状态会集中到一个比较大的对象上来,当应用变得非常复杂时,State对象就有可能变得相当臃肿。为了解决这个问题,vuex允许我们将store分割成模块,每个模块拥有自己的State、Getter、Mutation、Action甚至是子模块Module。
image.png
八、Vuex基本结构
image.pngimage.png
九、State
- 1、$store.state.msg
- 2、mapState
import { mapState } from 'vuex'
export default{
computed:{
//msg : state=>state.msg
...mapState(['msg']); //写法1
...mapState({ message : 'msg' }); //写法2
}
}
十、Getter
// vuex.js
getters:{
reverseMsg(state){
return state.msg.split('').reverse().join('-')
}
}
- 1、$store.getters.reverseMsg
- 2、mapGetters
import { mapGetters } from 'vuex'
export default{
computed:{
...mapGetters(['reverseMsg']);
}
}
十一、Mutation (不要进行一步操作)
//vuex.js
mutations:{
increate(state,payload){
state.count += payload
}
}
- $store.commit('increate',2)
- mapMutations
import { mapMutations} from 'vuex'
export default{
methods:{
...mapMutations(['increate']);
}
}
-
时光旅行
image.png
十二、Action
// vuex.js
actions:{
increateAsync(context,payload){
setTimeout(()=>{
context.commit('increate',payload)
},2000)
}
}
- $store.dispatch('increateAsync',5)
- mapActions
import { mapMutations} from 'vuex'
export default{
methods:{
...mapActions(['increateAsync']);
}
}
十三、Module
- 可以把单一状态树拆分成多个模块,每个模块都可以拥有自己的State,getters,Mutation,Action,嵌套子模块Module
const state ={}
const getters ={}
const mutations ={}
const actions ={}
export default {
namespaced:true,//开启命名空间
state,
getters,
mutations,
actions
}
- $store.state.Module名字.msg
...mapState('Module模块名字',['msg'])
...mapGetters('Module模块名字',['模块内getters'])
...mapMutations('Module模块名字',['模块内方法名'])
十四、Vuex严格模式
- 如果使用严格模式,在组件中修改state的时候回抛出错误
//vuex.js
export default new Vuex.store({
strict:true, // 开启
strict:process.env.NODE_ENV!=='production', // 生产环境开启
state:{},
getters:{},
mutations:{},
actions:{}
})
十五、VUEX插件介绍
- Vuex 的插件就是一个函数
- 这个函数接收一个store的参数
- vuex插件的使用
const myPlugin = store =>{
//当store初始化后调用
store.subscribe((mutation,state) =>{
//每次mutation之后调用
//mutation的格式为{ type,payload }
})
}
const store = new Vuex.Store({
plugins:[myPl]
})
十六、模拟VUEX
const _Vue = null
class Store {
constructor (options) {
const {
state = {},
getters = {},
mutations = {},
actions = {}
} = options
this.state = _Vue.observable(state)
this.getters = Object.create(null)
Object.keys(getters).forEach(key => {
Object.defineProperty(this.getters, key, {
get: () => getters[key](state)
})
})
this._mutation = mutations
this._actions = actions
}
commit (type, payload) {
this._mutation[type](this.state, payload)
}
dispatch (type, payload) {
this._actions[type](this, payload)
}
}
function install (Vue) {
_Vue = Vue
_Vue.mixin({
beforeCreate () {
if (this.$options.store) {
_Vue.prototype.$store = this.$options.store
}
}
})
}
export default {
Store,
install
}