Vue-状态管理
# Vuex
Vuex 是 Vue中的一套 公共数据管理工具 , 可将数据存到 vuex中 , 方便整个程序在任何组件 获取和修改当中的公共数据
API:https://vuex.vuejs.org/zh/ (opens new window)
GitHub: https://github.com/vuejs/vuex (opens new window)
CDN:https://cdn.bootcdn.net/ajax/libs/vuex/3.1.3/vuex.js (opens new window)
概念
State
: 变量Getters
: 获取变量 (计算属性同理)Mutations
: 更变变量 (同步方法处理)Action
: 设置方法 (异步方法处理 , 处理多个Mutation)Modules
: 模块化 (每个模块包含 state、mutaion、action、getter)
脚手架 : 点击跳转
应用步骤: (前提:两层嵌套组件)
引入 vue.js
创建 实例vuex对象
const <vuex对象名> = new Vuex.Store({ state() { return { <key>:<value> [, <key>:<value> ...] } } });
父组件引入 vuex对象 ==store: <vuex对象名>==
Vue.component(<组件名>, { store: <vuex对象>, })
应用 vuex数据 , 获取通过 插值表达式 进行获取
==this.$store.state.<属性key>==
示例
<div id="app">
<grandpa></grandpa>
</div>
....
<template id="grandpa">
<div>
<p>爷爷 {{this.$store.state.msg}}</p>
<father></father>
</div>
</template>
<template id="father">
<div>
<p>父亲 {{this.$store.state.msg}}</p>
<son></son>
</div>
</template>
<template id="son">
<div>
<p>儿子 {{this.$store.state.msg}}</p>
</div>
</template>
<script>
const d = new Vuex.Store({
state() {
return {
msg: "hello world"
}
}
});
// 爷爷
Vue.component("grandpa", {
template: "#grandpa",
store: d,
components: {
// 父亲
"father": {
template: "#father",
components: {
// 儿子
"son": {
template: "#son"
}
}
}
}
})
new Vue({
el: "#app"
})
</script>
渲染结果
<div id="app">
<div>
<p>爷爷 hello world</p>
<div>
<p>父亲 hello world</p>
<div>
<p>儿子 hello world</p>
</div>
</div>
</div>
</div>
# 方法共享
方法共享 可在不同组件之间均可使用的方法 , vuex中 mutations
对象 是专门保存操作共享数据的方法
关键字: mutations
一般情况不建议在组件中对Vuex共享数据直接修改 , 因为在多个组件中维护起来会比较麻烦 . 因此建议使用vuex共享的方法进行修改 , 维护时只需查看vuex的方法即可
注意
mutations中定义的方法 , 系统会自动传递 state参数(state保存的是共享数据
应用步骤: (前提:两层嵌套组件)
引入vuex.js
创建 实例Vuex对象
Vuex对象中编写方法
const <vuex对象名> = new Vuex.Store({ state() { return {....} }, mutations: { // 系统会自动传递 state参数 <方法名1>(state) { .... } [,<方法名2>(state) {....}] } })
父组件引入 vuex对象 ==store: <vuex对象名>==
组件方法调用vuex共享 ==this.$store.commit(<vuex对象方法名>[,<参数>])==
示例
<div id="app">
<no1></no1>
</div>
....
<template id="no1">
<div>
<button @click="add">加</button>
<button @click="sub">减</button>
<input type="text" :value="this.$store.state.count">
<no2></no2>
</div>
</template>
<template id="no2">
<div>
<button @click="add2">加</button>
<button @click="sub2">减</button>
<input type="text" v-model.number="val">
<p>{{this.$store.state.count}}</p>
</div>
</template>
<script>
const b = new Vuex.Store({
state() {
return {
count: 1
}
},
mutations: {
// 系统会自动传递 state参数
mAdd(state) {
state.count += 1;
},
mSub(state) {
state.count -= 1;
},
// 带参测试
mAdd2(state , num) {
state.count += num;
},
mSub2(state , num) {
state.count -= num;
}
}
})
Vue.component("no1", {
template: "#no1",
store: b,
components: {
"no2": {
template: "#no2",
data() {
return {
val: 0
}
},
// 组件2 带参应用
methods: {
add2() {
this.$store.commit("mAdd2", this.val)
},
sub2() {
this.$store.commit("mSub2", this.val)
}
}
}
},
methods: {
add() {
this.$store.commit("mAdd")
},
sub() {
this.$store.commit("mSub")
}
}
})
new Vue({
el: "#app"
})
</script>
# 计算属性共享
[计算属性](/vue/04/#computed 计算属性) 是为了在多组件中完好的利用缓存 , 从而提高效率
关键字: getters
应用步骤:(上面已经有大致步骤 , 因此展示主要代码)
在 vuex实例中 添加
getters
const <vuex对象名> = new Vuex.Store({ state() { return{ msg: "柏竹" } }, getters: { // 系统会自动传递 state参数 <计算属性名>(state) { console.log("执行了 formart") return state.msg + " Hello World " } } })
组件调用计算属性 , 获取通过 插值表达式 进行获取 ==this.$store.getters.<计算属性名>==
示例
<div id="app">
<no1></no1>
</div>
....
<template id="no1">
<div>
<p>no1 {{this.$store.getters.formart}}</p>
<p>no11 {{this.$store.getters.formart}}</p>
<no2></no2>
</div>
</template>
<template id="no2">
<div>
<p>no2 {{this.$store.getters.formart}}</p>
<p>no22 {{this.$store.getters.formart}}</p>
</div>
</template>
<script>
const b = new Vuex.Store({
state() {
return{
msg: "柏竹"
}
},
getters: {
formart(state) {
console.log("执行了 formart")
return state.msg + " Hello World "
}
}
})
Vue.component("no1",{
template:"#no1",
store: b,
components:{
"no2":{
template: "#no2"
}
},
data() {
return{
msg: "柏竹"
}
}
})
new Vue({
el:"#app"
})
</script>
# 模块化
在实际项目中会有多个模块
单个模块
const parmission = {
// 命名空间, 减少配置项的方法名冲突问题, 但引用需要模块名作为前缀
namespace: true,
const state = {
...
}
const mutations = {
...
}
const actions = {
...
}
}
// 暴露
export default parmission
模块 index管理
Vue.use(Vuex)
...
const store = new Vuex.Store({
modules: {
// parmission模块
parmission,
// 其他模块
user,
settings
}
})
提取
// 完整状态管理
this.$store
// 调用模块mutations (模块名/方法名)
// 引用了命名空间 (namespace: true) 建议
this.$store.commit("parmission/getName")
// 有参
this.$setore.commit("parmission/setName","bozhu12")
// 无命名空间
this.$store.commit("getName")
// 调用模块actions (用法和commit 一样)
this.$store.dispatch("parmission/getInfo")
# Pinia
Vuex处于维护模式 , 今后不会更新功能 , 因此使用 Pinia 进行状态管理 , 概念相关性较高 , 自行官网了解
官网 : https://pinia.vuejs.org (opens new window)
依赖
yarn add pinia
# 或者使用 npm
npm install pinia
全局引入
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
基本用法
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
postCreateData: {
fileList: [],
selectTagList: [],
content: ''
}
}),
getters: {
double: (state) => state.count * 2,
getFileList(state){
return state.postCreateData.fileList;
}
},
actions: {
increment() {
this.count++
},
},
})
// 外部访问
import { useCounterStore } from './counter'
const CounterStore = useCounterStore();
// 访问state
console.log(CounterStore.count)
console.log(CounterStore.postCreateData.content)
// 访问getters
console.log(CounterStore.double)
console.log(CounterStore.getFileList)
// 访问actions
console.log(CounterStore.increment())