0
点赞
收藏
分享

微信扫一扫

Vuex状态管理

求阙者 2022-04-23 阅读 78

组件间通信方式

组件内的状态管理流程

  1. state: 驱动应用的数据源
  2. view: 以声明方式将state 映射到视图
  3. actions: 响应在view 上的用户输入导致的状态变化

view --> actions —> state: 单项数据流

组件间通信方式

  1. 父组件给子组建的传值

    1. 父组件中给子组件通过相应的属性传值
    2. 子组件通过 props 接收数据
  2. 子组件给父组件的传值

    1. 自定义事件

    2. this.$emit( ‘fn’ , data)

      <Child @enlarge=" hS += $event "></Child>			// 行间可以通过 $event 接收子组件传递的值
      
  3. 不相关组件间的传值

    1. 自定义事件 eventBus : 中央事件总线

      const Bus = new Vue()			// 空vue实例
      
      bus.$emit('fn1', this.value)		// 触发事件
      
      bus.$on('fn1', () => {				// 注册事件
      	// ...
      })
      
  4. 其他常见方式

    1. $root

    2. $parent

    3. $children

    4. $refs ——> ref 获取子组件

      1. 在普通HTML标签上使用 ref, 获取到的是 DOM对象

      2. 在组件标签上使用 ref,获取到的是组件实例

        <input ref="input" type='text' v-model="value" />
        
        //...
        this.$refs.input.focus()
        
        // 如果是组件,可以获取组件中的属性或方法
        this.$refs.c.focus()
        this.$refs.c.value = 'abc'
        

      ref 容易导致数据管理的混乱。

简易的状态管理方案

  1. 多视图依赖同一状态
  2. 来自不同视图的行为需要变更同一状态

共享数据抽取出来,放在全局唯一的对象中管理。

Vuex的基本用法

Vuex

Vuex 采用集中式的方式存储需要存储的状态。

Vuex 作用:

  1. 进行状态管理

    1. 解决复杂组件通信
    2. 数据共享

Vuex 集成到了 devtools 中,提供了 time-travel 时光旅行、历史回滚的功能。

非必要的情况下不要使用Vuex, 大型的单页应用程序多视图依赖同一状态时使用。

Vuex 的核心概念

  1. Store:包含状态的容器,全局只有一个
  2. State: 唯一状态树,可以拆分成模块。响应式
  3. Getter: Vuex中的计算属性,可以缓存计算结果
  4. Mutation: 状态的变换必须要通过提交Mutation 来实现,只能是同步操作
  5. Action: 异步操作
  6. Module: 拆分Store 为多个模块

vuex 基本代码结构:

import  Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
	state: {
	
	},
	getters: {
	
	},
	mutations: {
	
	},
	actions: {
	
	},
	modules: {
	
	}
})


State 的使用:

// 组件中使用
<p>{{ $store.state.count }}</p>

// mapState 自动生成状态对应的计算属性, 简化 $store.state 的使用
import { mapState } from 'vuex'
export default {
	computed: {
		...mapState(['count', 'msg'])
	}
}

<p>{{ count }}</p>


// 如果组件中,有相同的属性名,则可以使用别名来处理
...mapState({ num: 'count', message: 'msg'})

Getters 的使用:

// store.js
getters: {
	reversMsg(state) {
		return  state.msg.reverse()
	}
}
// 组件中使用
<p>reverseMsg: {{ $store.getters.reverseMsg }}</p>

// 使用 mapGetters 简化 $store.getters
import { mapGetters } from 'vuex'
computed: {
	...mapGetters(['reverseMsg'])				// 也可使用 { } 的形式重命名
}


Mutations的使用:

// 组件中使用
<button @click="$store.commit('increate', 2)">Mutions</button>			// 通过commit() 提交到Mutation

// store.js
mutations: {
	increate(state, payload){			// payload 是 commit() 传递的第二个参数
		state.count += payload
	}
}

// 使用 mapMutations 简写 $store.commit(),   放在 methods中,而不是computed中
import {  mapMutations } from  'vuex'
methods: {
	...mapMutations(['increate'])
}
<button @click="increate(2)">Mutions</button>	

Mutations状态更改都要通过它, 只能进行同步操作,在浏览器vue-devtools插件 中,可以看到每一步的Mutations,以及历史回滚。

Action的使用:

// 异步更改数据,然后提交Mutations 
// 在组件中使用
<button @click="$store.dispatch('asyncIncreate', 4)"></button>	  // $store.dispatch() 调用action中定义的方法

// 使用 mapActions() 简化$store.dispatch() , 放在 methods 中
import {  mapActions } from  'vuex'
methods: {
	...mapActions(['asyncIncreate'])
}
<button @click="asyncIncreate(4)">Mutions</button>	

Modules 的使用:

$store.state.prodducts.xxx				// $store.state.模块名.模块成员

// carts.js
const state = {}
const mutations = {}
const actions = {}
const modules = {}

export default{
	namespaced: true,			// 开启命名空间
	state,
	mutations,
	actions,
	modules
}

// 使用 mapMutations 映射模块中的mutations
... mapMutations(['increate']),
... mapMutations('cart', ['setProducts'])			// 模块名,mutation中的方法

$store.commit('abc', 56)		// 如果多个模块中有 abc 的mutation, 它都会被执行

Vuex 严格模式

开启严格模式后,在组件中直接修改state会报错。

不要再生产模式下开启严格模式,会严格检查状态树,影响性能。

// store.js
export default new Vuex.Store({
	strict: process.env.NODE_ENV !== 'production',      // true   生产环境下不开启严格模式			
})

模拟vuex

// index.js
let  _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 => {				// 将参数getters处理后,放入 this.getters
			Object.defineProperty(this.getters, key, {
				get: () => getters[key](state)
			})
		})
		// 私有方法
		this._mutations = mutations
		this._actions = actions
	}
	
	commit(type, payload){
		this._mutations[type](this.state, payload)			// type对应的方法 
	}
	
	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
}
举报

相关推荐

0 条评论