vuex 配置使用解析 mutations响应式规则 Vue.delete/set 目录划分

用处

vuex专门用于解决共享数据问题,是将数据提升到顶层,不过他使用了一些特别的技巧,不仅让组件的依赖更加清晰,当数据变动时,仅渲染依赖该数据的组件
注意:并非所有数据都需要用vuex管理,通常vuex只管理那些需要被组件共享的数据
在实际开发中,一些逻辑特别复杂的数据,尽管不共享,也可能提取到vuex中进行管理

解析

结构
import Vue from 'vue'
import VueX from 'vuex'

Vue.use(VueX)

const store = new VueX.Store({
    state:{  // 仓库  
		count:0
		// 访问 this.$store.state.count
    },
    mutations:{  // 状态更新 只能通过mutations的方法修改 仓库数据
    	// 修改仓库内容  浏览器场景devtoos 可检测到修改信息 
    	// 不能执行异操作 不然检测的修改记录不准确
        
        // 事件类型:回调函数
        
        // 修改仓库数据
        // state 仓库  payload 参数(负荷:携带着某某)
        setCount(state, payload){
        	state.count = payload
        }
        
        
        // 通过mutations 更新
        
        普通提交风格
        // this.$store.commit('setCount',2) 
        // payload => 2
        
        特殊提交风格
        // this.$store.commit({
		// 	type:'setCount',
		// 	count:2,
		// 	age:18
		// }) 
		// payload => {type:'setCount',count:2,age:18}
    },
    actions:{  // 执行异步操作的地方
    
		// 操作mutations方法
		// 当前store对象  context.commit-> this.$store.commit
		operationCount(context, payload){
			context.commit('setCount',2)
		}
		// 调用 operationCount 
		// this.$store.dispatch('operationCount')
    },
    getters:{ // 类似于计算属性
        // 访问   this.$store.getters.xxx
        
        // state 仓库 gettes 当前gettes对象 可用来访问其它gettes方法
        getFun(state, gettes){
			// gettes.xxx
		}
		// 传递参数 默认是不能传递参数的  可返回一个函数 调用该函数传参数
		getParams(state){
			return function(par){
				return par*state.count
			}
		}
		// 调用 $store.getters.getParams(99)
		
    },
    modules:{  // 多个仓库整合 仓库模块划分
    
    }
})
export default store
单一状态树 state

Vuex提出使用单一状态树
Single Source of Truth => 单一数据源
即全局只使用一个 store 对象

getters使用

仓库

const store = new VueX.Store({
    state:{  
		count:2
    },
    getters:{
		powCount(state){
            return state.count*state.count
        },
        isPow(state, gettes){
			return gettes.powCount > 10
		},
		// 给 getter 传参 返回一个函数 调用该函数传参数
		getParams(state){
			return function(par){
				return par*state.count
			}
		}
		// 简化
		getParams: state => par => par*state.count
		
	}
})

组件使用

<template>
	<div>
		获取count的平方:{{computedCount}}
		获取count的平方:{{$store.getters.powCount}}
		count的平方是否大于10{{$store.getters.is20}}
		指定一个数乘以count {{$store.getters.getParams(99)}}
	</div>
</template>

<script>
export default{
	computed:{
		computedCount(){ // 直接获取然后计算
			return this.$store.state.count * this.$store.state.count 
		}
	}
}
</script>
mutations
mutations 提交风格

普通提交风格

// 触发
this.$store.commit('setCount',2) 

// 参数接收
mutations:{
	setCount(state, payload){
		//  payload => 2 
	}
}

特殊提交风格

// 触发
this.$store.commit({
	type:'setCount',
	count:2,
	age:18
}) 

// 参数接收
mutations:{
	setCount(state, payload){
		// payload => {type:'setCount',count:2,age:18}
	}
}
mutations 响应规则

Vuex中的store的state是响应式的,当state中的数据发生变化时,Vue组件会自动更新
这必须遵循一些Vuex对应的规则

  1. 提前在store中初始化好所需的属性(这些属性都会被加入响应式系统中,当属性发生变化时,会通知所有界面中用到该属性的地方,让界面发生刷新)
  2. 当给state中的对象添加新属性时,使用
    • 使用Vue.set(obj, 'newProp', 123)
    • 用新对象给旧对象赋值
  3. 当给state中的对象删除属性时
    • 使用Vue.delete(obj, 'prop')
state:{  
	obj:{
		name:"可响应的属性",
	}
},
mutations:{
	addNewProp(state){
		// 给state中的对象添加新属性
		// 直接添加是不可响应的
		state.obj['name2'] = '不可响应的属性'
		
		// 添加响应式属性 name3属性是可响应的
		Vue.set(state.obj, 'name3', '添加响应式属性')
		
		// 赋值一个新对象
		state.obj = {...state.obj, name3:'添加响应式属性'}
		
		// 删除属性 该方式删除不会响应
		delete state.obj.name
		
		// 删除响应式属性
		Vue.delete(state.obj, 'name')
	}
}
mutations 常量类型 名称使用常量

当项目增大时,Vuex管理的状态越来越多,需要更新的状态越来越多,那么意味着Mutations中的方法越来越多
方法过多,使用中需要花费大量的精力去记住这些方法,甚至是多个文件间来回切换,查看方法名称,甚至不是复制的时候,还会写错的情况。

mutations-types.js 保存方法名

export const INCREMENT = 'increment'
// 其它mutations类型
// ...

store.js

import Vue from 'vue'
import Vuex from 'vuex'
import {INCREMENT} from './mutations-types'

Vue.use(Vuex)
export default new Vuex.Store({
	state:{
	
	},
	mutations:{
		[INCREMENT]:function(state, payload){
			// ...
		}
	}
})

使用

import {INCREMENT} from './store/mutations-types'
export default{
	methods:{
		setFun(){
			this.$store.commit(INCREMENT)
		}
	}
}
mutations 同步函数

通常情况下,Vuex要求muations中的方法必须是同步方法
主要原因是当我们使用devtools时,可以让devtools帮助捕捉mutations的提交信息
如果是异步操作,那么devtools将不能很好的追踪这个操作什么时候完成
如果有异步操作 使用actions的方法 来操作mutations

actions

action 类似于Mutation,但是用来代替Mutation来进行异步操作的

actions:{  // 执行异步操作的地方
    
	// 操作mutations方法
	// 当前store对象  context.commit-> this.$store.commit
	operationCount(context, payload){
		context.commit('setCount',payload)
	}
	// 不能直接操作state
	// context.state.xxx = xxx
	
	// 调用 operationCount 
	// this.$store.dispatch('operationCount', 2)
},
modules

Vue使用单一状态树,那么也就意味着有很多状态都会交给Vuex来管理
当应用变得非常复杂时,store对象就有可能变得非常臃肿,为了解决这个问题,Vuex允许将store分割成模块,而没个模块都有自己的 state mutations actions getters 等

基本使用

结构

modules:{
	a:{
		state:{},
		mutations:{},
		getters:{},
		actions:{},
		modules:{....}
	}
}
const moduleA = {
	state:{
		name:"moduleA"
	},
	mutations:{
		updataName(state, payload){
			console.log('moduleA -- mutations')
		}
	},
	getters:{
		// state 对应单前模块的getters
		// getters对应单前模块的getters
		// 在模块里面有第三个参数 rootState 获取根State
        repeatName(state, getters, rootState){
            return state.name.repeat(10)
        }
    },
     actions:{
        actRname(context, payload){
            // context.rootGetters
            // context.rootState
            console.log(context)
            setTimeout(() => {
                // 只能提交该模块的mutations方法
                context.commit('upName',payload)
            }, 3000);
        }
    }
}
const moduleB = {
	state:{},
	mutations:{},
	getters:{},
}

cons store = new Vuex({
	modules:{
		moduleA,
		moduleB
	}
})
// 相当于 
//state:{
//	moduleA:{...}
//}


// 调用
this.$store.state.moduleA.name
this.$store.commit('updataName')
{{$store.getters.repeatName}}
this.$store.dispatch('actRname')
命名空间 namespaced
const moduleA = {
	namespaced: true,
	mutations:{
		setisLoading(state, payload){
			//...
		}
	}
	//...
}

// 调用模块A下面的 mutations 的 setisLoading方法 
this.$store.commit('moduleA/setisLoading',true)

vuex使用

安装

npm i vuex

main.js配置

import vuex from 'vuex'
Vue.use(vuex )
const store = new vuex.Store({
	// 配置
	// state:{} //仓库
})
new Vue({
	render:h=>h(App)
	router,
	store
}).$mount("#app")

或者

import {Store} from 'vuex'
new Store({})
分离模块文件配置

新建 store/index.js

import Vue from 'vue'
import vuex from 'vuex'
import user from './user' // 导入用户信息仓库

Vue.use(vuex)
const store = new vuex.Store({
	// 配置
	modules:{
		// user(仓库名称):user
		user, // 简写
		// ... 其他仓库
	}  
})
export default store

新建 store/user.js

// 用户信息仓库
export default {
	state:{
		user:{
			data:{}, // 用户信息
			isLogin:false // 登录状态
		}
	}
}

main.js

import Vue from 'vue'
import App from './App.vue'
import store from './store'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
  store,
}).$mount('#app')

仓库结构
在这里插入图片描述
20200721205143871.png)

访问仓库数据
直接访问
this.$store.state.user.isLogin
通过计算属性
computed:{
	isLogin(){
		return this.$store.state.user.isLogin
	}
}
vuex辅助函数
import {mapState} from 'vuex'
computed:mapState('user',['data','isLogin'])

this.isLogin // false

访问多个 访问会以前面的为准

computed:{
	...mapState('user',['data','isLogin']),
	...mapState('user2',{
		user2data:'data',
		user2isLogin:'isLogin'
	}),
}
修改仓库数据 mutation

数据的改动必须要提交commit 一个mutation
在vuex中,提交mutation是数据变化的唯一原因
在 mutation 中不能出现副作用(不能改动或使用外部的数据,ajax,其他异步行为…)会影响vue监听工具的使用

mutations:{
	setData(state,data){
		/// setTimeout
	}
}

配置

// user
export default {
    namespaced:true, // 开启命名空间
    state:{
        data:[],
        isLoading:false
    },
    mutations:{
        // 这里配置多种变异方式
        // state:原来的状态
        // payload:负荷 
        setisLoading(state,payload){
            state.isLoading = payload
        },
        setData(state,data){
            state.data = data
        }
    }
}

调用

// 开启命名空间的写法
this.$store.commit('user/setisLoading',true)
// 没有开启命名空间的写法
this.$store.commit('setisLoading',true)
actions 业务逻辑处理
export default {
    namespaced:true, // 开启命名空间
    state:{
        data:[],
        isLoading:false
    },
    mutations:{
        setisLoading(state,payload){
            state.isLoading = payload
        },
        setData(state,data){
            state.data = data
        }
    },
    actions:{
    	// context 等同于 this.$store 只能传递一个参数payload
		async initData(context,params){
			// 由于是在当前命名空间 可不写 channels/
            context.commit('setisLoading',true);
            let dat = await getNewsChanges() //接口获取数据
            context.commit('setData',dat.data);
            context.commit('setisLoading',false);
		}
    }
}

调用 dispatch 触发action

this.$store.dispatch('channels/initData',1)

store 变化逻辑

直接通过mutation 改动仓库数据
在这里插入图片描述
通过action 改动仓库数据
在这里插入图片描述

在main.js 触发dispatch

// 初始化数据
store.dispatch('user/initData')

store 目录结构

在这里插入图片描述
actions.js

export default {
	asyncCount(context, payload){
		setTimeout(()=>{
			context.commit('addCount',payload)
		})
	}
}

getters.js

export default {
	count(state){
		return state.count > 10
	}
}

mutations.js

export default {
	addCount(state, payload){
		state.count = payload
	}
}

index.js

import Vue from 'vue'
import Vuex from 'vuex'
import mutations from './mutations'
import actionsfrom from  './actions'
import getters from  './getters'
import moduleA from  './modules/moduleA'

const state = {
	count:0
}

Vue.use(Vuex)

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

modules/moduleA.js

export default {
	namespaced:true, // 开启命名空间
	state:{},
	mutations:{},
	actions:{},
	getters:{}
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值