状态管理

@ Pinia
Introduction
. Vue3 采用 Pinia 管理状态
. Pinia 是 Vue 专属的集中式状态管理库,使用大菠萝作为 logo
. 仓库 stores 是一个保存全局状态 state 和业务逻辑的实体;可以在整个应用中访问的数据
. 不与组件树绑定,而承载着全局状态
. 状态管理出现之前,使用共享组件完成对数据的共享使用;共享数据的修改通过共享组件发送自定义事件完成 - 任何一个使用它的组件都可以修改,不太容易维护
. Vue2 采用 vuex
Concepts
State - 驱动整个应用的数据源;是 store 的核心。应先定义能代表应用或反映应用状态的 state - 相当于组件中的 data
Getter - 对状态的一种声明式映射 - 相当于组件中的 computed
Action - 根据用户的交互对数据源的操作 - 相当于组件中的 method
关系
Deployment
. 强烈建议在创建项目时,选择状态管理;项目创建完毕后,可以直接使用;不建议新手手动安装部署使用
. 仓库通常集中保存在项目的 stores 目录(应提前创建好),并按照功能创建单独的仓库文件
. 强烈建议通过复制计时器仓库 counter.js 并修改的方式创建新的仓库
. 仓库在 onMounted 之前就已经准备好 - 兵马未动,粮草先行
1. Installation
npm i pinia
2. Import
. 在入口文件 main.js 引入并创建使用
import './assets/main.css'

import { createApp } from 'vue'
import App from './App.vue'
//1. 导入
import { createPinia } from 'pinia'
//2. 创建
const pinia = createPinia()
const app = createApp(App)
//3. 使用
app.use(pinia)
app.mount('#app')
counter.js
引入 defineStore 库及其它必要库
使用 defineStore 创建仓库实例,其中:

. 第一个参数 counter 是你的应用中 Store 的唯一 ID,Pinia 将用它来连接 store 和 devtools

. 第二个参数接收 option 对象或 setup 函数;setup 函数和组合式 API 类似,且功能更灵活

导出仓库示例(函数;需执行后才可以得到仓库实例),以 use 开头且以 Store 结尾命名,如 useCounterStore
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useCounterStore  = defineStore('counter', ()=>{
  //state - ref()
  const count = ref(0)
  
  //getters - computed()
  const doubleCount = computed( () => count.value * 2 )
  
  //action - function()
  const increment = () => count.value++

  return { count, msg, doubleCount, increment }
})
组件使用 Store

. 逻辑 - 引入仓库、创建仓库实例、使用仓库数据

. 创建仓库实例前无法使用

. 仓库中的状态应指定初始值,否则其中的方法只有执行后才能拿到值

import { useCounterStore } from '@/stores/counter';
const store = useCounterStore();
console.log('store', store);

. 结构 - 渲染仓库数据;这里采用内联事件

<div>{{ store.count }}</div>
<div>{{ store.doubleCount }}</div>
<div @click="store.increment">store handle</div>
Warning
解构 使得 store 中的数据会丢失响应,方法不会
import { useCounterStore } from '@/stores/counter';
const store = useCounterStore();
const { count, increment } = store;
<div @click="increment">仓库数据 - {{ count }}</div>
使用 storeToRefs 包保持数据响应式 - 不建议;命名冲突。。。可读性不好。。。运维困难。。。
storeToRefs 面向的是数据,不是方法;所以不需要对方法进行特别处理
import { useCounterStore } from '@/stores/counter';
import { storeToRefs } from 'pinia';
const store = useCounterStore();
const { count } = storeToRefs(store);