vue之vuex日常使用

196 阅读4分钟

vuex:直接上手

将学习到:

  • Vuex状态管理基础用法,通过同步异步修改状态;
  • 命名空间的使用;
  • 动态添加;
  • vuex热更新。

新建store.js

import Vuex from "vuex"

// 采用函数的方式,可解决服务端渲染内存溢出等问题
export default () => {
	return new Vuex.Store({
	    strict: false, 
	    // 默认是false,则通过this.$store.state.count = 10,是可以更改count的值,但是官方不推荐我们这么使用 
	    // 如果修改为true,则通过this.$store.state.count = 10是不可以更改的,报错
	    // strict: true , 不建议在正式环境使用,但是开发环境可用于规范团队开发,可通过process.env.xxx等方式区别环境
        state: {
            count: 0
        },
        mutations: {
            updateCount(state,count) {
                state.count = count
            }
        },
        getters: {
        	getterCount(state) {
        		return state.count + 100
        	}
        },
        actions: {
        	updateCountAsync(store,data) {
        		store.commit('updateCount', data)
        	}
        },
        // 理论上模块可以无限嵌套下去
        modules: {
        	// 模块aaa,可以叫命名空间aaa
        	aaa: {
        		state: {
        			text: 100
        		}
        	},
        	bbb: {
        		state: {
        			text: 200
        		}
        	}
        }
    })
}

入口文件引入

...
import Vue from "vue"
import Vuex from "vuex"
import createStore from 'xxx/store.js'
...
Vue.use(Vuex) // 一定要在使用vuex前,使用Vue.use()方法注册Vuex
const store = createStore()

new Vue({
    ...
    store
    ...
})

.vue页面取值方式

方法11this.$store.state.count 
2this.$store.getters.getterCount
方法2import { mapState,mapMutations,mapGetters,mapActions } from "vuex"
computed: {
	// 1.1、获取count值方式:
	...mapState(['count']), // 如果遇到不兼容...写法,则cnpm i babel-preset-stage-l -D 
	// 1.2、获取count值方式:
	...mapState({
		counter: count // 重新命名,并赋值counter
	})
	// 1.3、获取count方式:
	...mapState({
		counter: state => state.count // 函数的方式,可以使用其变量,和方法1的第1方式基本一样。
	})
	// 2.1获取getters中的属性
	...mapGetters(['getterCount']) // 获取属性的方法都类似,可以用{ getterCounter: getterCount }等方式。
}
配置babel-preset-stage-l:
在.babelrc文件中:
{
	"presets": [
		...
		"stage-l"
	],
	...
}

.vue页面更新方式

// 一般的方式
1this.$store.commit(fn,data) // fn:updateCount
2this.$store.dispatch(fn,data) // fn: updateCountAsync
// 使用mapXxx方式
mounted() {
	this.updateCount(2);
	this.updateCountAsync(3)
},
mothods: {
	...mapMutations(['updateCount']), // ...mapMutations({ updateCount: updateCount })
	...mapActions(['updateCountAsync']), ...mapActions({ updateCountAsync: updateCountAsync }),
}

扩展 - 对store.js

import Vuex from "vuex"
// 采用函数的方式,可解决服务端渲染内存溢出等问题
export default () => {
	return new Vuex.Store({
	    ... // 省略
        // 理论上模块可以无限嵌套下去
        modules: {
        	// 模块aaa,可以叫命名空间aaa
        	aaa: {
        		namespaced: true, // 命名空间的作用
        						// 如果默认为false,则所有模块中mutations、actions中的方法不可重复,如:updateAText是不可重复的,那么...mapMutions(['updateAText'])是可以使用的
        						// 如果默认为true,则每个模块中mutations、actions出现重复的无所谓,他们有命名空间区别,则在用法方面需要加上aaa/(即模块名称):...mapMutions(['aaa/updateAText'])
        		state: {
        			text: 100
        		},
        		mutations: {
        			updateAText(state,data){
        				// 默认情况下,这里的state是当前模块aaa下得state
        				state.text = data
        			}
        		},
        		actions: {
        			actionAText({state,getters,rootState}){
        				// state: 是aaa模块下的state
        				// getters: 是aaa模块下的getters
        				// rootState: 是根模块下(全局)的state,如rootState.state、rootState.bbb.text
        				console.log(rootState)
        				commit("updateAText", 120,{root: false})
        				commit("updateCount", 222,{root: true})
        				// root: 默认情况下为false,则commit的方法为aaa模块下的方法
        				// root: 默认情况下为true,则commit的方法为全局的commit方法
        			}
        		},
        		getters: {
        			getterAText(state,getters,rootState) {
        				// state: 是aaa模块下的state
        				// getters: 是aaa模块下的getters
        				// rootState: 是根模块下(全局)的state,如rootState.state、rootState.bbb.text
        				return state.text + 50
        			}
        		}
        	},
        	bbb: {
        		namespaced: true, // 命名空间的作用
        		state: {
        			text: 200
        		},
        		actions: {
        			actionBText({state,getters,rootState}){
        				// 调用aaa模块commit方法:
        				commit("aaa/updateAText", 202,{root: true})
        				// root: 默认情况下为true,则commit的方法为全局的commit方法
        			}
        		},
        	}
        }
    })
}

.vue文件使用之mapXxx

// 常规方法取值:
computed: {
	textAAA() {
		return this.$store.state.aaa.text
	},
	textBBB() {
		return this.$store.state.bbb.text
	},
}
// mapXxx方法,则不能通过.的方式了, 因为分模块了(即命名空间)
computed: {
	...mapState({
		textAAA: state => state.aaa.text,
		textBBB: state => state.bbb.text
	}),
	...mapGetters(['getterAText']) // 当namespaced: false
	...mapGetters(['aaa/getterAText']) // 当namespaced: true,这里在视图中使用就会有问题了
									// ...mapGetters({getterAText: 'aaa/getterAText' // 当namespaced: true,这里在视图中使用就会有问题了,则改成对象形式即可}) 
},
mounted() {
	this.updateAText(101) // 当namespaced: false
	this[aaa/updateAText](101) // 当namespaced: true
	console.log(this['aaa/getterAText']) // 当namespaced: true
},
methods: {
	...mapMutions(['updateAText'])  // 当namespaced: false
	...mapMutions(['aaa/updateAText'])  // 当namespaced: true ...mapMutions({ updateAText: 'aaa/updateAText' })  // 当namespaced: true
	
	...mapActions(['aaa/actionAText']) // ...mapActions({actionAText:aaa/actionAText})
}

动态加载Vuex模块

// 入口文件引入
...
const store = createStore()
store.registerModule("ccc",{
	state: {
		text: 3
	}
})
// vuex为我们提供registerModule动态注册模块
// 其他的使用方式一样
// 解绑 store.unregisterModule('ccc')

vuex热更新

import Vuex from "vuex"

// 采用函数的方式,可解决服务端渲染内存溢出等问题
export default () => {
	return new Vuex.Store({
	    ... // 省略,并在这个基础上改造一下
    })
}
// 并在这个基础上改造一下,如下:
export default () => {
	const store = new Vuex.Store({
	    ... // 省略,并在这个基础上改造一下
    })
    // 热更替
    if(module.hot) {
    	module.hot.accept([
    		"./state/state",
    		"./mutations/mutations",
    		"./actions/actions",
    		"./getters/getters"
    	],()=>{
    		const newState = require("./state/state").default // ./state/state分模块时,文件夹路径
    		const newMutations = require("./mutations/mutations").default
    		const newActions = require("./actions/actions").default
    		const newGetter = require("./getters/getters").default
    		store.hotUpdate({
    			state: newState,
    			mutations: newMutations,
    			actions: newActions,
    			getters: newGetter
    		})
    	})
    }
    return store;
}
vuex // 文件结构
---state
	------state.js   // const newState = require("./state/state").default
---mutations
	------mutations.js  // require("./mutations/mutations").default
	... // 省略
---store.js

状态管理之watch

// 入口文件引入
...
const store = createStore()
store.watch(state => {
	return state.count + 100
},(newCount) => {
	console.log(newCount)
})
store.subscribe((mutation,state)=>{
	// 订阅 监听mutations发生变化时执行
})
store.subscribeAction((mutation,state)=>{
	// 订阅 监听Actions发生变化时执行
})
// 当我们在commit中的方法为什么只能传递两个参数,当我们在subscribe,subscribeAction中能一目了然的知道那些变化。
// 使用场景:制作vuex插件

vuex插件

const store = new Vuex.Store({
	...
	plugin: [
		(store) => {
			store.watch(state => {
                return state.count + 100
            },(newCount) => {
                console.log(newCount)
            })
			store.subscribe((mutation,state)=>{
            	// 在vue初始化的时候执行,插件可以在这时候做点什么
            })
            store.subscribeAction((mutation,state)=>{
                // 订阅 监听Actions发生变化时执行
            })
		}
	]
})