vue使用webgl(vue使用pinia (vue2/vue3))
pinia是什么?Pinia 是 Vue.js 的轻量级状态管理库
官方网站:Pinia
中文文档: 介绍 | Pinia 中文文档
pinia与vuex4
相同
是vue 官方 状态管理工具(作者是 Vue 核心团队成员) 是vue开发者工具支持pinia不同
pinia相比vuex4 ,对于vue3的 兼容性 更好 pinia相比vuex4 ,具备完善的 类型推荐 => 对 TS 支持很友好 Pinia的 API 设计非常接近 Vuex 5 的提案 。
vuex只能有一个根级别的状态, pinia 直接就可以定义多个根级别状态pinia核心概念
state: 状态 actions: 修改状态(包括同步和异步 ,pinia中没有mutations) getters: 计算属性一 、使用
1. 安装pinia vue2/vue3 通用
yarn add pinia # 或者使用 npm npm install pinia2.如果是脚手架的创建的项目可以在安装 ,会自动创建一个出一个实例 ,帮助你快速引入pinia
vue add vue-cli-plugin-pinia3.使用 pinia
store/index.js import { defineStore } from pinia // 创建store,命名规则: useXxxxStore // 参数1:store的唯一表示 // 参数2:对象 ,可以提供state actions getters export const useCounterStore = defineStore(counter, { // data里中的数据 state: () => ({ count: 1 }), // 计算属性 getters: { double: state => state.count * 2 }, // 相当于 vue中的 methods 既可以写同步代码也可以写异步 actions: { addCount () { this.count++ } } })vue2: Home.vue
<template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> <div> pinia中的count值 {{count}}</div> <div>pinia中的计算属性 {{double}}</div> <button @click="addCount">count +1 </button> <button @click="getCount">拿到count的值</button> </div> </template> <script> // @ is an alias to /src import { mapState, mapActions } from pinia import { useCounterStore } from @/store export default { name: Home, computed: { ...mapState(useCounterStore, [count, double]) }, methods: { ...mapActions(useCounterStore, [addCount]), getCount () { console.log(this.count) } } } </script>vue3
<template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> <div> pinia中的count值 {{store.count}}</div> <div>pinia中的计算属性 {{store.double}}</div> <button @click="addCount">count +1 </button> <button @click="getCount">拿到count的值</button> </div> </template> <script > import { useCounterStore } from @/store export default { setup () { const store = useCounterStore() const addCount = () => { // 数据+1 store.count++ // 使用$patch 修改数据 好处是可以使用修改多个数据 // store.$patch({ // count: store.count + 1 // }) } return { store, addCount } } } </script>二 、持久化 vue3/vue2通用
持久化插件:Pinia Plugin Persist
安装命令
npm add pinia-plugin-persist或
yarn add pinia-plugin-persistvue2持久化
main.js
import Vue from vue import App from ./App.vue import router from ./router import { createPinia, PiniaVuePlugin } from pinia import VueCompositionAPI from @vue/composition-api // 引入持久化组件 若不想持久化 可不使用 import piniaPersist from pinia-plugin-persist const pinia = createPinia() pinia.use(piniaPersist) Vue.use(PiniaVuePlugin) Vue.use(VueCompositionAPI) Vue.config.productionTip = false new Vue({ router, pinia, render: h => h(App) }).$mount(#app)store/index.js
import { defineStore } from pinia export const useCounterStore = defineStore(counter, { // data里中的数据 state: () => ({ count: 1 }), persist: { enabled: true, // 开启本地存储 strategies: [ { key: counter1, // 修改当前存储的键名 若不修改则是上面的id storage: localStorage // 修改当前的存储方式 ,如果不填 则存储方式为sessionstorage } ] } })vue3持久化
main.js
import Vue from vue import App from ./App.vue import router from ./router import { createPinia, PiniaVuePlugin } from pinia import VueCompositionAPI from @vue/composition-api // 引入持久化组件 若不想持久化 可不使用 import piniaPersist from pinia-plugin-persist const pinia = createPinia() pinia.use(piniaPersist) Vue.use(PiniaVuePlugin) Vue.use(VueCompositionAPI) Vue.config.productionTip = false new Vue({ router, pinia, render: h => h(App) }).$mount(#app)store/index.js
import { defineStore } from pinia export const useCounterStore = defineStore(counter, { // data里中的数据 state: () => ({ count: 1 }), persist: { enabled: true, // 开启本地存储 strategies: [ { key: counter1, // 修改当前存储的键名 若不修改则是上面的id storage: localStorage // 修改当前的存储方式 ,如果不填 则存储方式为sessionstorage } ] } })三 、storeToRefs
使用storeToRefs可以保证解构出来的数据也是响应式的 。
在模板中使用数据时 ,要加上模块的名字 ,例如:
<template> <div> {{counter.count}} </div> </template> <script setup> import { useCounterStore } from @/store const counter = useCounterStore() </script>如果我们想省略counter 第一个思路 解构
<script setup> import { useCounterStore } from @/store const counter = useCounterStore() const { count } = counter </script>如果直接从pinia中结构 ,会丢失响应式
storeToRefs
可以保证解构出来的数据也是响应式的 。
const { state属性名1 , state属性名2 } = storeToRefs(模块名)使用
<script setup> import { storeToRefs } from pinia import { useCounterStore } from @/store const counter = useCounterStore() const { count } = storeToRefs(counter) </script>使用storeToRefs可以保证解构出来的数据也是响应式的
四 、pinia模块化
src ├── store │ ├── 模块1.js │ └── 模块2.js ├── pages │ ├── Home.vue │ └── Login.vue └── main.js在某个.vue中使用模块时,先import useXXXStore from ./模块, 然后 const xxx = useXXXStore() ,来使用 。如果在导入第二个模块就需要写两次
import { useCounterStore } from @/store/counter import { useCounterUser } from @/store/user const counter = useCounterStore() const counter = useCounterUser()改进
在复杂项目中 ,不可能把多个模块的数据都定义到一个store中,一般来说会一个模块对应一个store ,最后通过一个根store进行整合
src ├── store │ ├── modules │ │ ├── user.js │ │ └── counter.js │ └── index.js // 根store ├── pages │ └── 页面.vue └── main.jsmodule/counter.js
import { defineStore } from pinia const useUserStore = defineStore(counter, { state: () => ({ count: 1 }), getters: { double: state => state.count * 2 }, actions: { addCount () { this.count++ } }, persist: { enabled: true } }) export default useUserStorestore/index.js
// 1. 分别导入各个模块 import useCounterStore from ./module/counter import useUserStore from ./module/user // 2. 统一导出useStore方法 export default function useStore () { return { counter: useCounterStore(), user: useUserStore() } }store/user.js
import { defineStore } from pinia const useUserStore = defineStore(user, { state: () => ({ name: 奥特曼, age: 18 }), getters: { double: state => state.age * 2 }, actions: { editUserName () { this.name = 迪迦 } }, persist: { enabled: true } }) export default useUserStore注意: 每个文件中的 defineStore(id,{}) 中的id不要重复 否则在index.js 调用时以第一次调用为准
组件中使用
<template> <div> {{count}} {{name}} <button @click="addCount">+1</button> </div> </template> <script setup> import { storeToRefs } from pinia // 导入工具函数 import useStore from @/store // 解构一下 const { counter, user } = useStore() // 使用storeToRefs可以保证解构出来的数据也是响应式的 const { count } = storeToRefs(counter) const { name } = storeToRefs(user) const { addCount } = counter </script>创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!