1 什么是状态管理
其实是数据管理
但是为了更好的指出是由于状态的变化导致数据的变化(响应式数据)
,我们称之为状态管理.
2 Vuex的状态管理
组件只能直接读取state,而不能直接修改state,必须通过mutation才能修改.(pinia可以直接读取和修改state)
3 Vuex的安装
npm install vuex
4 创建Store
文件结构
1 创建store,使用state(核心一)
import { createStore } from 'vuex'
const store = createStore({
state: () => ({
// 模拟数据
// counter: 100,
rootCounter: 100,
}),
//用于修改state的mutations
mutations: {
increment(state) {
state.counter++
}
}
})
export default store
2 使用和修改state,解构state获取数据
<template>
<div class="app">
//模板中使用
<h2>Home当前计数: {{ $store.state.counter }}</h2>
//options API 使用
<h2>Computed当前计数: {{ storeCounter }}</h2>
//setUP API 使用
<h2>Setup当前计数: {{ counter }}</h2>
// 修改state
<button @click="increment">+1</button>
</div>
</template>
<script>
export default {
computed: {
storeCounter() {
return this.$store.state.counter
}
}
}
</script>
<script setup>
import { toRefs } from 'vue'
import { useStore } from 'vuex'
const store = useStore()
//解构state获取数据,counter,可以是多个数据,起别名等(推荐)
const { counter } = toRefs(store.state)
function increment() {
// store.state.counter++
store.commit("increment")
}
</script>
<style scoped>
</style>
5 getters的基本使用 对state数据进行加工(核心二)
inde.js代码
const store = createStore({
state: () => ({
// 模拟数据
// counter: 100,
rootCounter: 100,
name: "coderwhy",
level: 100,
avatarURL: "http://xxxxxx",
friends: [
{ id: 111, name: "why", age: 20 },
{ id: 112, name: "kobe", age: 30 },
{ id: 113, name: "james", age: 25 }
],
}),
getters: {
// 1.基本使用
doubleCounter(state) {
return state.counter * 2
},
totalAge(state) {
return state.friends.reduce((preValue, item) => {
return preValue + item.age
}, 0)
},
// 2.在该getters属性中, 获取其他的getters
message(state, getters) {
return `name:${state.name} level:${state.level} friendTotalAge:${getters.totalAge}`
},
// 3.getters是可以返回一个函数的, 调用这个函数可以传入参数(了解)
getFriendById(state) {
return function(id) {
const friend = state.friends.find(item => item.id === id)
return friend
}
}
},
vue代码
<template>
<div class="app">
<!-- <button @click="incrementLevel">修改level</button> -->
<h2>doubleCounter: {{ $store.getters.doubleCounter }}</h2>
<h2>friendsTotalAge: {{ $store.getters.totalAge }}</h2>
<h2>message: {{ $store.getters.message }}</h2>
<!-- 根据id获取某一个朋友的信息 -->
<h2>id-111的朋友信息: {{ $store.getters.getFriendById(111) }}</h2>
<h2>id-112的朋友信息: {{ $store.getters.getFriendById(112) }}</h2>
</div>
</template>
6 Mutation基本使用,state的修改(核心三)
重要的原则: 不要在mutation方法中执行异步操作
mutations: {
increment(state) {
state.counter++
},
changeName(state, payload) {
state.name = payload
},
incrementLevel(state) {
state.level++
},
changeInfo(state, newInfo) {
state.level = newInfo.level
state.name = newInfo.name
// 重要的原则: 不要在mutation方法中执行异步操作
},
methods: {
changeName() {
// this.$store.state.name = "李银河"
//带外部参数的修改
this.$store.commit("changeName", "王小波")
},
incrementLevel() {
this.$store.commit("incrementLevel")
},
changeInfo() {
//外部参数是一个对象
this.$store.commit("changeInfo", {
name: "王二",
level: 200
})
}
}
}
</script>
7 actions的基本使用 ,异步派发(核心四)
使用dispatch函数进行分发
actions: {
incrementAction(context) {
// console.log(context.commit) // 用于提交mutation
// console.log(context.getters) // getters
// console.log(context.state) // state
context.commit("increment")
},
changeNameAction(context, payload) {
context.commit("changeName", payload)
},
},
<template>
<div class="home">
<h2>当前计数: {{ $store.state.counter }}</h2>
<button @click="counterBtnClick">发起action修改counter</button>
<h2>name: {{ $store.state.name }}</h2>
<button @click="nameBtnClick">发起action修改name</button>
</div>
</template>
<script>
export default {
methods: {
counterBtnClick() {
this.$store.dispatch("incrementAction")
},
nameBtnClick() {
this.$store.dispatch("changeNameAction", "aaa")
}
}
}
</script>
<script setup>
</script>
<style scoped>
</style>
actions的异步操作
8 module的基本使用,抽出模块(核心五)
定义一个单独的home.js文件
export default {
state: () => ({
// 服务器数据
banners: [],
recommends: []
}),
mutations: {
changeBanners(state, banners) {
state.banners = banners
},
changeRecommends(state, recommends) {
state.recommends = recommends
}
},
actions: {
fetchHomeMultidataAction(context) {
return new Promise(async (resolve, reject) => {
// 3.await/async
const res = await fetch("http://123.207.32.32:8000/home/multidata")
const data = await res.json()
// 修改state数据
context.commit("changeBanners", data.data.banner.list)
context.commit("changeRecommends", data.data.recommend.list)
resolve("aaaaa")
})
}
}
}
导入index.js
//导入模块对象
import homeModule from './modules/home'
//导入模块
modules: {
home: homeModule,
}
使用xxx.vue文件
<template>
<div class="home">
<h2>Home Page</h2>
<ul>
<!-- 使用数据时需要模块名 state.modulename.xxx -->
<template v-for="item in $store.state.home.banners" :key="item.acm">
<li>{{ item.title }}</li>
</template>
</ul>
</div>
</template>
<script>
</script>
<script setup>
import { useStore } from 'vuex'
// 调用方法时,不需要模块名
const store = useStore()
store.dispatch("fetchHomeMultidataAction").then(res => {
console.log("home中的then被回调:", res)
})
</script>
<style scoped>
</style>