1、vuex
import { createStore } from "vuex"
import axios from 'axios'
import { INCREMENT_N } from './mutation-types'
const store = createStore({
state() {
return {
counter: 100,
name: "why",
age: 18,
height: 1.88,
books: [
{ name: "深入Vuejs", price: 200, count: 3 },
{ name: "深入Webpack", price: 240, count: 5 },
{ name: "深入React", price: 130, count: 1 },
{ name: "深入Node", price: 220, count: 2 },
],
discount: 0.6,
banners: []
};
},
getters: {
totalPrice(state, getters) {
let totalPrice = 0
for (const book of state.books) {
totalPrice += book.count * book.price
}
return totalPrice * getters.currentDiscount
},
currentDiscount(state) {
return state.discount * 0.9
},
totalPriceCountGreaterN(state, getters) {
return function(n) {
let totalPrice = 0
for (const book of state.books) {
if (book.count > n) {
totalPrice += book.count * book.price
}
}
return totalPrice * getters.currentDiscount
}
},
nameInfo(state) {
return `name: ${state.name}`
},
ageInfo(state) {
return `age: ${state.age}`
},
heightInfo(state) {
return `height: ${state.height}`
}
},
mutations: {
increment(state) {
state.counter++;
},
decrement(state) {
state.counter--;
},
// 10 -> payload
// {n: 10, name: "why", age: 18} -> payload
[INCREMENT_N](state, payload) {
console.log(payload);
state.counter += payload.n
},
addBannerData(state, payload) {
state.banners = payload
}
},
actions: {
// 放函数
// 1.参数问题
incrementAction(context, payload) {
console.log(payload)
setTimeout(() => {
context.commit('increment')
}, 1000);
},
// 2.context的其他属性
decrementAction({ commit, dispatch, state, rootState, getters, rootGetters }) {
commit("decrement")
},
getHomeMultidata(context) {
return new Promise((resolve, reject) => {
axios.get("http://123.207.32.32:8000/home/multidata").then(res => {
context.commit("addBannerData", res.data.data.banner.list)
resolve({name: "coderwhy", age: 18})
}).catch(err => {
reject(err)
})
})
}
}
});
export default store;
2、setup()中使用state 和 getters
// useState.js
import { mapState } from 'vuex'
import { useMapper } from './useMapper'
export function useState(mapper) {
return useMapper(mapper, mapState)
}
// useGetters.js
import { mapGetters } from 'vuex'
import { useMapper } from './useMapper'
export function useGetters(mapper) {
return useMapper(mapper, mapGetters)
}
// useMapper.js
import { computed } from 'vue'
import { matState, useStore } from 'vuex'
export function useMapper(mapper, mapFn) {
// 拿到store 对象
const store = useStore();
// 获取到对应的对象的functions: { name: function, age: function }
const storeStateFns = mapFn(mapper);
// 对数据进行转换
const storeState = {};
Object.keys(storeStateFns).forEach(fnKey => {
const fn = storeStateFns[fnKey].bind({ $store: store });
storeState[fnKey] = computed(fn)
})
return storeState
}
// Home.vue
<template>
<div>
<h2>{{counter}} - {{name}}</h2>
<h2>{{sCounter}} - {{sName}}</h2>
</div>
</template>
<script>
import { useState } from '../hooks/useState'
export default {
setup() {
const storeState = useState(["counter", "name"]);
const storeState2 = useState({
sCounter: state => state.counter,
sName: state => state.name
})
return {
...storeState,
...storeState2
}
}
}
</script>
mutations
一、mutations 的使用
<template>
<div>
<h2>当前计数: {{ $store.state.counter }}</h2>
<hr>
<button @click="$store.commit('increment')">+1</button>
<button @click="$store.commit('decrement')">-1</button>
<button @click="addTen">+10</button>
<hr>
</div>
</template>
<script>
import { INCREMENT_N } from '../store/mutation-types'
export default {
methods: {
addTen() {
// this.$store.commit('incrementN', 10)
// this.$store.commit('incrementN', {n: 10, name: "why", age: 18})
// 另外一种提交风格
this.$store.commit({
type: INCREMENT_N,
n: 10,
name: "why",
age: 18
})
}
}
}
</script>
<style scoped>
</style>
二、mutations 的辅助函数
<template>
<div>
<h2>当前计数: {{ $store.state.counter }}</h2>
<hr>
<button @click="increment">+1</button>
<button @click="add">+1</button>
<button @click="decrement">-1</button>
<button @click="increment_n({n: 10})">+10</button>
<hr>
</div>
</template>
<script>
import { mapMutations, mapState } from 'vuex'
import { INCREMENT_N } from '../store/mutation-types'
export default {
methods: {
...mapMutations(["increment", "decrement", INCREMENT_N]),
...mapMutations({
add: "increment"
})
},
setup() {
const storeMutations = mapMutations(["increment", "decrement", INCREMENT_N])
return {
...storeMutations
}
}
}
</script>
<style scoped>
</style>
3、Actions
一、actions 的使用
<template>
<div>
<h2>当前计数: {{ $store.state.counter }}</h2>
<hr>
<button @click="increment">+1</button>
<button @click="decrement">-1</button>
<hr>
</div>
</template>
<script>
import axios from 'axios'
export default {
methods: {
increment() {
this.$store.dispatch("incrementAction", {count: 100})
},
decrement() {
// 3.派发风格(对象类型)
this.$store.dispatch({
type: "decrementAction"
})
}
},
mounted() {
this.$store.dispatch("getHomeMultidata")
},
setup() {
}
}
</script>
<style scoped>
</style>
二、Actions 的辅助函数 mapActions
1、optionsApi
<template>
<div>
<button @click="incrementAction">+1</button>
<button @click="decrementAction">-1</button>
<button @click="add">+1</button>
<button @click="sub">-1</button>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
methods: {
// 数组方式
...mapActions(["incrementAction", "decrementAction"]),
// 对象方式
...mapActions({
add: "incrementAction",
sub: "decrementAction"
})
}
}
</script>
2、compositionApi
<template>
<div>
<button @click="incrementAction">+1</button>
<button @click="decrementAction">-1</button>
<button @click="add">+1</button>
<button @click="sub">-1</button>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
setup() {
const actions = mapActions(["incrementAction", "decrementAction"])
const actions2 = mapActions({
add: "incrementAction",
sub: "decrementAction"
})
return {
...actions,
...actions2
}
}
}
</script>
4、modules
一、modules 的使用
// store/index.js
import { createStore } from "vuex"
import home from './modules/home'
import user from './modules/user'
const store = createStore({
state() {
return {
rootCounter: 100
}
},
getters: {
doubleRootCounter(state) {
return state.rootCounter * 2
}
},
mutations: {
increment(state) {
state.rootCounter++
}
},
modules: {
home,
user
}
});
export default store;
// store/home.js
const homeModule = {
namespaced: true,
state() {
return {
homeCounter: 100
}
},
getters: {
doubleHomeCounter(state, getters, rootState, rootGetters) {
return state.homeCounter * 2
},
otherGetter(state) {
return 100
}
},
mutations: {
increment(state) {
state.homeCounter++
}
},
actions: {
incrementAction({commit, dispatch, state, rootState, getters, rootGetters}) {
commit("increment")
commit("increment", null, {root: true})
// dispatch
// dispatch("incrementAction", null, {root: true})
}
}
}
export default homeModule
// store/user.js
const userModule = {
namespaced: true,
state() {
return {
userCounter: 10
}
}
}
export default userModule
// pages/module的基本使用.js
<template>
<div>
<h2>{{ $store.state.rootCounter }}</h2>
<h2>{{ $store.state.home.homeCounter }}</h2>
<h2>{{ $store.state.user.userCounter }}</h2>
</div>
</template>
二、modules 的命名空间
// store/index.js
import { createStore } from "vuex"
import home from './modules/home'
import user from './modules/user'
const store = createStore({
state() {
return {
rootCounter: 100
}
},
getters: {
doubleRootCounter(state) {
return state.rootCounter * 2
}
},
mutations: {
increment(state) {
state.rootCounter++
}
},
modules: {
home,
user
}
});
export default store;
// store/home.js
const homeModule = {
namespaced: true,
state() {
return {
homeCounter: 100
}
},
getters: {
doubleHomeCounter(state, getters, rootState, rootGetters) {
return state.homeCounter * 2
},
otherGetter(state) {
return 100
}
},
mutations: {
increment(state) {
state.homeCounter++
}
},
actions: {
incrementAction({commit, dispatch, state, rootState, getters, rootGetters}) {
commit("increment")
commit("increment", null, {root: true})
// dispatch
// dispatch("incrementAction", null, {root: true})
}
}
}
export default homeModule
// pages/modules 的命名空间.vue
<template>
<div>
<h2>root:{{ $store.state.rootCounter }}</h2>
<h2>home:{{ $store.state.home.homeCounter }}</h2>
<h2>user:{{ $store.state.user.userCounter }}</h2>
<hr>
<!-- <h2>{{ $store.getters.doubleHomeCounter }}</h2> -->
<h2>{{ $store.getters["home/doubleHomeCounter"] }}</h2>
<button @click="homeIncrement">home+1</button>
<button @click="homeIncrementAction">home+1</button>
</div>
</template>
<script>
export default {
methods: {
homeIncrement() {
this.$store.commit("home/increment")
},
homeIncrementAction() {
this.$store.dispatch("home/incrementAction")
}
}
}
</script>
三、modules 的辅助函数
<template>
<div>
<hr>
<h2>{{ homeCounter }}</h2>
<h2>{{ doubleHomeCounter }}</h2>
<!-- <h2>{{ doubleRootCounter }}</h2> -->
<button @click="increment">home+1</button>
<button @click="incrementAction">home+1</button>
<hr>
</div>
</template>
<script>
import { createNamespacedHelpers, mapState, mapGetters, mapMutations, mapActions } from "vuex";
import { useState, useGetters } from '../hooks/index'
// 写法三:
const { mapState, mapGetters, mapMutations, mapActions } = createNamespacedHelpers("home")
export default {
computed: {
// 1.写法一:
...mapState({
homeCounter: state => state.home.homeCounter
}),
...mapGetters({
doubleHomeCounter: "home/doubleHomeCounter"
}),
// 2.写法二:
...mapState("home", ["homeCounter"]),
...mapGetters("home", ["doubleHomeCounter"]),
// 3.写法三:
...mapState(["homeCounter"]),
...mapGetters(["doubleHomeCounter"])
},
methods: {
// 1.写法一:
...mapMutations({
increment: "home/increment"
}),
...mapActions({
incrementAction: "home/incrementAction"
}),
// 2.写法二
...mapMutations("home", ["increment"]),
...mapActions("home", ["incrementAction"]),
// 3.写法三:
...mapMutations(["increment"]),
...mapActions(["incrementAction"]),
},
setup() {
// {homeCounter: function}
const state = useState(["rootCounter"])
const rootGetters = useGetters(["doubleRootCounter"])
const getters = useGetters("home", ["doubleHomeCounter"])
const mutations = mapMutations(["increment"])
const actions = mapActions(["incrementAction"])
return {
...state,
...getters,
...rootGetters,
...mutations,
...actions
}
}
}
</script>
// hooks/useMappper.js
import { computed } from 'vue'
import { useStore } from 'vuex'
export function useMapper(mapper, mapFn) {
// 拿到store独享
const store = useStore()
// 获取到对应的对象的functions: {name: function, age: function}
const storeStateFns = mapFn(mapper)
// 对数据进行转换
const storeState = {}
Object.keys(storeStateFns).forEach(fnKey => {
const fn = storeStateFns[fnKey].bind({$store: store})
storeState[fnKey] = computed(fn)
})
return storeState
}
// hooks/useState.js
import { mapState, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'
export function useState(moduleName, mapper) {
let mapperFn = mapState
if (typeof moduleName === 'string' && moduleName.length > 0) {
mapperFn = createNamespacedHelpers(moduleName).mapState
} else {
mapper = moduleName
}
return useMapper(mapper, mapperFn)
}
// hooks/useGetters.js
import { mapGetters, createNamespacedHelpers } from 'vuex'
import { useMapper } from './useMapper'
export function useGetters(moduleName, mapper) {
let mapperFn = mapGetters
if (typeof moduleName === 'string' && moduleName.length > 0) {
mapperFn = createNamespacedHelpers(moduleName).mapGetters
} else {
mapper = moduleName
}
return useMapper(mapper, mapperFn)
}