vue devtool
用来调试vuex的数据
devtool安装
在谷歌浏览器中的拓展程序中下载vue devtool
打开调试在vue中可以进行调试
安装vuex
npm i vuex
vuex基本使用
建立一个store文件夹
import { createStore } from 'vuex'
const store = createStore({
state() {
return {
counter: 100
}
},
mutations: {
increment(state, payload) {
state.counter++;
},
decrement(state, payload) {
state.counter--;
}
}
});
export default store
在main.js引入
import { createApp } from 'vue'
import App from './App.vue'
import store from './store';
const app = createApp(App);
app.use(store);
app.mount('#app');
在组件中使用,使用方法使用commit
<div>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
{{ $store.state.counter }}
</div>
methods: {
increment() {
this.$store.commit("increment");
},
decrement() {
this.$store.commit("decrement");
}
}
mapState
通过mapState方法,可以取出store的state里的属性,将其放在computed中,在template中可以直接引用
<template>
<div>
{{ name }}
{{ age }}
</div>
</template>
<script>
import { mapState } from 'vuex';
export default {
computed: {
...mapState(['name', 'age'])
},
}
</script>
方法里是对象的话可以自定义属性的名称
...mapState({
rename: state => state.name
})
在setup中使用vuex
setup() {
const store = useStore();
const reage = computed(() => store.state.age)
return {
reage
}
},
mapState返回的是一个对象中包含许多函数,在optionApi中computed中可以结构,因为computed接收一个个带有返回值的函数,但是setup中不能这么写
setup() {
const store = useStore();
const reage = computed(() => store.state.age)
const storeStateFns = mapState(['name', 'age', 'counter']);
const storeState = {};
Object.keys(storeStateFns).forEach(fnKey => {
const fn = storeStateFns[fnKey].bind({$store: store}) //绑定this,因为返回值是this.$store.state,如果不绑定会报错
storeState[fnKey] = computed(fn)
})
return {
reage,
...storeState
}
},
也可以将封装这个方法封装到一个文件中 src/hooks/useState.js
import { mapState, useStore } from 'vuex';
import { computed } from 'vue';
export function useState(mapper) {
const store = useStore();
const storeStateFns = mapState(mapper);
const storeState = {};
Object.keys(storeStateFns).forEach(fnKey => {
const fn = storeStateFns[fnKey].bind({$store: store}) //绑定this,因为返回值是this.$store.state,如果不绑定会报错
storeState[fnKey] = computed(fn)
})
return storeState
}
在.vue文件中使用
setup() {
const storeState = useState(['counter', 'name', 'age'])
return {
...storeState
}
},
vuex中getters的使用
如果在vuex中某些属性需要变化后使用,可以使用getters,类似于computed
mutations: {
increment(state) {
state.counter++;
},
decrement(state) {
state.counter--;
}
},
getters: {
recounter(state, getters) {
return state.counter * 2
}
}
使用$store.getters.recounter调用
mapgetters使用
getters: {
recounter(state) {
return state.counter * 2
}
}
//.vue文件
import { mapState, useStore, mapGetters } from 'vuex';
computed: {
...mapGetters(['recounter'])
},
在setup中使用
setup() {
const store = useStore();
const reCounter = computed(() => store.getters.recounter)
return {
reCounter
}
},
与mapState类似,可以对mapGetters进行一个封装
import { mapGetters, useStore } from 'vuex';
import { computed } from 'vue';
export function useState(mapper) {
const store = useStore();
const storeStateFns = mapGetters(mapper);
const storeState = {};
Object.keys(storeStateFns).forEach(fnKey => {
const fn = storeStateFns[fnKey].bind({$store: store}) //绑定this,因为返回值是this.$store.state,如果不绑定会报错
storeState[fnKey] = computed(fn)
})
return storeState
}
除了调用函数不同,上面的封装有许多共同之处,所有可以合并为一个
mapMutation
setup() {
const storeMutations = mapMutations(["increment", decrement])
return {
...storeMutations
}
}
action的使用
- Action提交的是mutation,而不是直接变更状态
- Action可以包含任意异步操作
actions: {
incrementAction(context) {
setTimeout(() => {
context.commit('increment');
}, 1000);
}
}
methods: {
increment() {
this.$store.dispatch('incrementAction')
},
decrement() {
this.$store.commit("decrement");
}
}
mapAction使用
与mapState使用相似
methods: {
...mapActions(["incrementAction"]),
//或者传入对象
...mapActions({
add: "incrementAction"
}),
}
对于action,一般是返回一个promise,使得外面可以获取到请求的返回值
incrementAction(context) {
return new Promise((resolve, reject) => {
setTimeout(() => {
context.commit('increment');
}, 1000);
resolve()
})
}
module的使用
为了使代码结构更加清晰,可以使用module 建立一个user.js文件夹
const userModule = {
state: {
name: 'juju'
}
}
export default userModule
在主入口中引入
const store = createStore({
modules: {
user
},
在app.vue中使用
{{ $store.state.user.name }}
当使用模块中的state或mutation时,默认会做一个合并,如果要区分他们的写法,在独立模块中设置namespaced属性
const userModule = {
namespaced: true,
state: {
name: 'juju'
},
getters:{
rename(state, getters, rootState, rootgetters) {
return state.name + 'hh'
}
}
}
export default userModule
取得getter中的数据
{{ $store.getters["user/rename"] }}
调用mutation方法
this.$store.commit("user/increment")
dispatch同理 对于辅助函数的使用,可以采用:
import { createNamespacedHelpers } from 'vuex'
const { mapState, mapGetters, mapMutations } from createNamespacedHelpers('home')
///
...mapActions(["incrementAction"]),
nexttick的使用
将回调推迟到下一个DOM更新周期之后执行,在更改了一些数据以等待DOM更新后立即使用他
import {nextTick} from 'vue'
nextTick(() => {
//一些操作
})