一、官网介绍为什么使用pinia
Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。 如果您熟悉 Composition API,您可能会认为您已经可以通过一个简单的 export const state = reactive({}). 这对于单页应用程序来说是正确的,但如果它是服务器端呈现的,会使您的应用程序暴露于安全漏洞。 但即使在小型单页应用程序中,您也可以从使用 Pinia 中获得很多好处:
- dev-tools 支持
- 跟踪动作、突变的时间线
- Store 出现在使用它们的组件中
- time travel 和 更容易的调试
- 热模块更换
- 在不重新加载页面的情况下修改您的 Store
- 在开发时保持任何现有状态
- 插件:使用插件扩展 Pinia 功能
- 为 JS 用户提供适当的 TypeScript 支持或 autocompletion
- 服务器端渲染支持
二、代码实践
2.1、安装
pnpm add pinia
2.2、main.ts
import { createApp } from 'vue' import '@/styles/index.less' import '@/styles/reset.less' import App from './App.vue' import ElementPlus from 'element-plus' import 'element-plus/dist/index.css' import Antd from 'ant-design-vue' import 'ant-design-vue/dist/antd.css' import router from "./routers/index"; import { api } from './api/index' import { createPinia } from 'pinia' import piniaPersist from 'pinia-plugin-persist' // pinia持久化 import 'vue-global-api'; const app = createApp(App) const pinia = createPinia() pinia.use(piniaPersist) app.use(ElementPlus) app.use(Antd) app.use(router) app.use(pinia) app.config.globalProperties.$api = api app.mount('#app')
2.3、src/views/stores/index.ts
import { defineStore } from "pinia"; import { ref, computed } from "vue" // count1 是 id 须唯一 // options方法 export const useCountStore = defineStore('count1',{ // 在大多数情况下,state 都是你的 store 的核心。人们通常会先定义能代表他们APP 的 state。 // 在 Pinia 中,state 被定义为一个返回初始状态的函数。这使得Pinia 可以同时支持服务端和客户端。 state: () => { // 类似vue2的 data,data(){return{}} 防止服务端数据污染;----推荐使用箭头函数,为了完整类型推理; return { // 所有属性将自动推断出他们的类型 counter: 0 } }, persist: { // 持久化 enabled: true, }, getters: { // 相当于computed 计算属性 doubleCount (state){ return state.counter * 2 } }, actions: { // 相当于methods addCounter(){ // this指向对应的store仓库 this.counter += 1 } } }) // count2 是 id 须唯一 // setup方法 export const useCount2Store = defineStore('count2', ()=> { const counter = ref(1) // state const gettersCounter = computed(()=>{ return counter.value + 5 }) function addCounter(){ counter.value += 1 } return { counter, gettersCounter, addCounter} })
2.4、src/views/pinia/index.vue
<template> <div class="container"> <div>pinia-options</div> <div>count1.counter: {{ count1.counter }}</div> <div>count1.doubleCount {{ count1.doubleCount }}</div> <div @click="count1.addCounter()"> count1.counter: addCount+=1 </div> <div @click="changeCount1()"> count1.counter: addCount+=2 </div> <div>pinia-setup</div> <div>count2.counter: {{ count2.counter }}</div> <div>count2.gettersCounter {{ count2.gettersCounter }}</div> <div @click="count2.addCounter()"> count2.counter: addCount++ </div> <div @click="changeCount2()"> count2.counter: addCount+=2 </div> </div> </template> <script setup lang="ts"> import { useCountStore, useCount2Store } from '@/views/stores/index' const count1 = useCountStore() const count2 = useCount2Store() console.log('count1:', count1) console.log('count2:', count2) const changeCount1 = () => { // 方式一、需要修改数据时直接修改 count1.counter += 2 // 方式二、如果需要修改多个,可以使用pinia的$patch方法,推荐使用 // count1.$patch({ // counter: count1.counter += 2 // }) // 方式三、对于复杂的方法可以封装actions的函数 // count1.$patch((state)=>{} // state.counter = count1.counter += 2 // ) // 方式四、对于复杂的方法可以封装actions的函数 // count1.addCounter } const changeCount2 = () => { count2.counter += 2 } </script> <style scoped lang="less"> </style>
2.5、浏览器展示