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页面取值方式
方法1:
1、this.$store.state.count
2、this.$store.getters.getterCount
方法2:
import { 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页面更新方式
// 一般的方式
1、this.$store.commit(fn,data) // fn:updateCount
2、this.$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发生变化时执行
})
}
]
})