目录
4. state 的映射:如何在template 中不需要通过$store.state 取值,直接通过state 中的名字来取值
1. 在options API 的computed 计算属性中使用mapState() 映射函数
2. 在composition API 的computed 计算属性中使用mapState() 映射函数(不推荐)
3. 在composition API 中通过toRefs (推荐)(直接对state 解构,并且包裹ref )
5. getters 支持返回一个函数,可以对getters 传入参数
6. getters 的映射:如何在template 中不需要通过$store.getters 取值,直接通过getters 中的名字来取值
2. composition API 中使用mapState()(不推荐)
3. 在composition API 中通过toRefs(直接对getters 解构,并且包裹ref )
4. 在composition API 中通过computed 对单个getter 进行监听(推荐)
三. mutations ( 更改vuex 中store 中的状态的唯一方法是提交mutation )
4. mutaions 的映射:直接通过mutaions 中的名字来调用方法
1. options API 中使用mapMutations()
2. composition API 中使用mapMutations()
5. mutations 中不要执行异步操作(方便devtool 中记录mutations 的日志)
1. 在options 中使用mapActions 辅助函数
2. 在composition 中使用mapActions 辅助函数
2. 默认获取getters mutations actions 时不需要加模块名称,但是存在命名冲突问题
3. 使用namespaced: true 获取getters mutations actions
一. state
1. Vuex 的状态存储是响应式的
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 100
})
})
export default store
2. 在template 中使用state
<h2>{{ $store.state.counter }}</h2>
3. 在script 中使用state
import { useStore } from 'vuex'
const store = useStore()
console.log(sotre.state.counter)
4. state 的映射:如何在template 中不需要通过$store.state 取值,直接通过state 中的名字来取值
1. 在options API 的computed 计算属性中使用mapState() 映射函数
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 100,
name: "why"
})
})
export default store
1. 数组写法
<h2>{{ counter}}</h2>
<h2>{{ name }}</h2>
<script>
import { mapState } from 'vuex'
export default {
computed: {
// 数组写法
...mapState(["counter", "name"])
}
}
</script>
2. 对象写法(当有state 和 data 中的数据存在命名冲突时,可以通过对象写法修改state 中数据的名字)
<h2>{{ sCouner}}</h2>
<h2>{{ sName}}</h2>
<script>
import { mapState } from 'vuex'
export default {
computed: {
// 对象写法
...mapState({
sCouner: state => state.sCounter,
sName: state => state.sName
})
}
}
</script>
2. 在composition API 的computed 计算属性中使用mapState() 映射函数(不推荐)
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 100,
name: "why"
})
})
export default store
<h2>{{ cCounter }}</h2>
<h2>{{ cName }}</h2>
<script setup>
import { computed } from 'vue'
import { mapState, useStore } from 'vuex'
const store = useStore()
const cCounter = computed(counter.bind({ $store: store }))
const cName = computed(name.bind({ $store: store }))
</script>
3. 在composition API 中通过toRefs (推荐)(直接对state 解构,并且包裹ref )
<h2>{{ sCounter }}</h2>
<h2>{{ name }}</h2>
<script setup>
import { toRefs } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
// 起别名 添加默认值 counter: sCounter = 0
const { counter: sCounter = 0, name } = toRefs(store.state)
</script>
二. getters (类似于computed)
1. getters 的基本使用
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 100,
users: [
{id: 1, name: "aaa", age: 20},
{id: 2, name: "bbb", age: 30},
{id: 3, name: "aaa", age: 40}
]
}),
getters: {
doubleCounter(state) {
return state.counter++
},
totalAge(state) {
return state.users.reduce(( preValue, item ) => {
return preValue + item.age
}, 0)
}
}
})
export default store
2. 在template 中使用getters
<h2> {{ $store.getters.doubleCounter }} </h2>
<h2> {{ $store.getters.totalAge }} </h2>
3. 在script 中使用getters
import { useStore } from 'vuex'
const store = useStore()
console.log( sotre.getters.doubleCounter )
4. 在当前getters 中获取其他的getters
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 100
users: [
{id: 1, name: "aaa", age: 20},
{id: 2, name: "bbb", age: 30},
{id: 3, name: "aaa", age: 40}
]
}),
getters: {
totalAge(state) {
return state.users.reduce(( preValue, item ) => {
return preValue + item.age
}, 0)
},
message(state, getters) {
return `counter: ${state.counter} firendsTotalAge: ${getters.totalAge}`
}
}
})
export default store
5. getters 支持返回一个函数,可以对getters 传入参数
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 100
users: [
{id: 1, name: "aaa", age: 20},
{id: 2, name: "bbb", age: 30},
{id: 3, name: "aaa", age: 40}
]
}),
getters: {
getFriendById(state) {
return function(id) {
const friend = state.users.find(item => item.id === id)
return friend
}
}
}
})
export default store
<h2> {{ $store.getters.getFriendById(1) }} </h2>
6. getters 的映射:如何在template 中不需要通过$store.getters 取值,直接通过getters 中的名字来取值
1. options API 中使用mapState()
<h2>{{ doubleCounter }}</h2>
<h2>{{ totalAge }}</h2>
<h2>{{ message }}</h2>
<h2>{{ getFriendsById }}</h2>
<h2>{{ DoubleCounter }}</h2>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
// 数组语法
...mapGetters(["doubleCounter", "totalAge", "message", "getFriendsById"])
// 对象语法(可以用来添加getters 的别名)
...mapGetters({
DoubleCounter: "doubleCounter"
})
}
}
</script>
2. composition API 中使用mapState()(不推荐)
<h2>{{ doubleCounter }}</h2>
<h2>{{ totalAge }}</h2>
<h2>{{ message }}</h2>
<h2>{{ getFriendsById }}</h2>
import { computed } from 'vue'
import { mapGetters, useStore } from 'vuex'
const store = useStore()
const { message: messageFn } = mapGetters(["message"])
const message = computed(messageFn.bind({ $store:store }))
3. 在composition API 中通过toRefs(直接对getters 解构,并且包裹ref )
<h2>{{ message }}</h2>
import { toRefs } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
const { message } = toRefs( store.getters )
4. 在composition API 中通过computed 对单个getter 进行监听(推荐)
const message = computed( () => store.getters.message )
三. mutations ( 更改vuex 中store 中的状态的唯一方法是提交mutation )
1. 基本使用
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
name: "why"
}),
metutions: {
changeName(state) {
state.name = "coder"
}
}
})
export default store
// Vue 3
const store = useStore()
function change() {
store.commit("changeName")
}
// Vue 2
function change() {
this.$store.commit("changeName")
}
2. 给mutation 传递参数
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
name: "why",
age: 18
}),
metutions: {
// payload 是自己起的
// 传递过来的参数通过payload 接收
changeInfo(state, payload) {
state.name = payload.newName
state.age= payload.newAge
}
}
})
export default store
function change() {
// (mutation 的函数名, 传递的参数)
store.commit("changeInfo", {
newName: "coder",
newAge: 20
})
// 传递的参数可以是一个基本数据类型,也可以是对象
store.commit("changeName", "coder")
}
3. 使用常量编写mutation 的名字
export const CHANGE_NAME = "changeInfo"
import CHANGE_INFO from './mutation_types.js'
mutations: {
[CHANGE_INFO](state, payload) {
state.name = payload.newName
state.age= payload.newAge
}
}
import CHANGE_INFO from './mutation_types.js'
function change() {
store.commit( CHANGE_INFO , {
newName: "coder",
newAge: 20
})
}
4. mutaions 的映射:直接通过mutaions 中的名字来调用方法
1. options API 中使用mapMutations()
import { mapMutations } from 'vuex'
export default {
methods: {
...mapMutations("changeName", CHANGE_INFO)
}
}
<button @click="changeName('coder')"></button>
// 调用时不能使用常量,需要使用常量的值
// const CHANGE_NAME = "changeInfo"
<button @click="changeInfo({name: 'coder', age: 20})"></button>
2. composition API 中使用mapMutations()
import { mapMutations, useStore } from 'vuex'
import { CHANGE_INFO } from '@store/mutation_types'
const store = useStore()
const mutations = mapMutations(['changeName', CHANGE_INFO])
const newMutations = {}
Object.keys(mutations).forEach(key => {
newMutations[key] = mutations[key].bind({ $store: store })
})
const { changeName, changeInfo } = newMutations
5. mutations 中不要执行异步操作(方便devtool 中记录mutations 的日志)
四. actions (异步操作)
1. 基本使用
- actions 提交的是mutations, 而不是直接变更状态
- actions 可以包含任意异步操作
- 参数:context, context 是一个store 实例均有相同方法和属性的context 对象,所以可以从其中获取到commit 方法来提交一个mutation ,或者通过context.state 和context.getters 来获取state 和getters
mutations: {
increment(state) {
state.counter++
}
},
actions: {
// payload 是传递过来的参数
incrementAction(context, payload) {
console.log(context.commit)
console.log(context.state)
console.log(context.getters)
context.commit("increment", payload)
}
}
<h2>{{ $store.state.counter }}</h2>
<button @click="actionBtnClick"></button>
methods: {
actionBtnClick() {
// 不传递参数
this.$store.dispatch("incrementAction")
// 传递参数
this.$store.dispatch("incrementAction", "aaa")
}
}
2. actions 的分发操作
add() {
this.$store.dispatch("increment")
}
// 携带参数
add() {
this.$store.dispatch("increment", { count: 100 })
}
add() {
// 以对象的形式分发
this.$store.dispatch({
type: "increment",
count: 100
})
}
3. mapActions 辅助函数
1. 在options 中使用mapActions 辅助函数
// 没有参数
<h2>{{ $store.state.counter }}</h2>
<button @click="incrementAction"></button>
// 携带参数
<h2>{{ $store.state.name}}</h2>
<button @click="changeNameAction("aaa")"></button>
import { mapActions } from 'vuex'
methods {
...mapActions(["increment", "changeNameAction"])
}
2. 在composition 中使用mapActions 辅助函数
import { useStore, mapActions } from 'vuex'
const store = useStore()
const actions = mapActions(["incrementAction", "changeNameAction"])
const newActions = {}
Object.keys(actions).forEach(key => {
newActions[key] = actions[key].bind({ $store: store })
})
const {incrementAction, changeNameAction} from = newActions
4. 使用基本的做法,不使用mapActions
function increment() {
store.dispatch("incrementAction")
}
5. 在actions 中进行异步操作
state: {
banner: []
}
mutations: {
changeBanner(state, banners) {
state.banner = banners
}
}
actions: {
async fetchHomeMultidataAction(context) {
//1. 返回promise 给promise 设置then
fetch("http://123.207.32.32:8080/home/mutidata").then(
res => { console.log(res.data) }
)
// 2. promise 的链式调用
fetch("http://123.207.32.32:8080/home/mutidata").then(
res => res.json()
).then(data => {
console.log(data)
})
// 3.await/async
const res = await fetch("http://123.207.32.32:8080/home/mutidata")
const data = await res.json()
console.log(data)
// 修改state 中的数据
context.commit("changeBanner", data.banner)
}
}
actions: {
function fooAction() {
return new Promise( async (resolve, reject) => {
const res = await fetch("http://")
const data = await res.json()
context.commit("changeBanners", data.banner)
context.commit("changeRecommends", data.recommend)
resolve(res.data)
})
}
}
store.dispatch("fooAction").then(res => {
console.log(res)
})
五. modules
1. 基本使用( 模块中的state )
// store/index.js
import { createStore } from 'vuex'
import homeModule from './modules/home'
const store = createStore({
state: () => ({}),
modules: {
home: homeModule
}
})
export default store
// store/modules/home.js
export default {
state: () => ({
banners: []
}),
mutations: {}
}
<h2>{{ $store.state.home.banners }}</h2>
2. 默认获取getters mutations actions 时不需要加模块名称,但是存在命名冲突问题
// store/index.js
import { createStore } from 'vuex'
import countModule from './modules/count'
const store = createStore({
state: () => ({
rootCount: 100
}),
modules: {
count: countModule
}
})
export default store
// store/modules/count.js
const counter = {
state: () => ({
count: 10
}),
getters: {
doubleCount(state, getters, rootState) {
return state.count + rootState.count
}
},
mutations: {
incrementMutation(state) {
state.count++
}
},
actions: {
incrementAction(context) {
context.commit("incrementMutation")
}
}
}
export default counter
// getters mutations actions 默认是不需要跟模块名字
<h2>{{ $store.getters.doubleCount }}</h2>
foo() {
store.dispatch("incrementAction")
}
3. 使用namespaced: true 获取getters mutations actions
// store/modules/info.js
export default {
namespaced: true
state: () => ({
name: 'why',
age: 18
}),
getters: {
doubleAge(state, getters, rootState, rootGetters) {
return state.age * 2
}
},
mutations: {
ageMutation(state) {
state.age++
}
},
actions: {
// context = { commit, dispatch, state, rootState, getters, rootGetters }
ageAction(context) {
context.commit("ageMutation")
}
}
}
// info 是模块名称
<h2> {{ store.state.info.age }}</h2>
<h2> {{ store.getters["info/doubleAge"]}}
store.commit("info/ageMutation")
store.dispatch("info/ageAction")
4. 在module 中修改root 的state
// 需要再module 中通过actions 进行修改
actions: {
changeRootAction({commit, dispatch, state, rootState, getters, rootGetters}) {
// 修改当前module 中的内容
commit("changeNameMutation", "kobe");
// 修改root 中的内容
commit("changeRootNameMutation", "kobe", {root: true})
dispatch("changeRootNameAction", "kobe", {root: true})
}
}