书接上回 vue3常见组件通信方式
1.Pinia的相关信息介绍
1.Pinia的简介:
Pinia 起始于 2019 年 11 月左右的一次实验,其目的是设计一个拥有组合式 API 的 Vue 状态管理库。
2.为什么要使用Pinia:
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的话,你可能会认为可以通过一行简单的 export const state = reactive({})
来共享一个全局状态。对于单页应用来说确实可以,但如果应用在服务器端渲染,这可能会使你的应用暴露出一些安全漏洞。 而如果使用 Pinia,即使在小型单页应用中,你也可以获得如下功能:
- Devtools 支持
- 追踪 actions、mutations 的时间线
- 在组件中展示它们所用到的 Store
- 让调试更容易的 Time travel
- 热更新
- 不必重载页面即可修改 Store
- 开发时可保持当前的 State
- 插件:可通过插件扩展 Pinia 功能
- 为 JS 开发者提供适当的 TypeScript 支持以及自动补全功能。
- 支持服务端渲染
3.为什么取名Pinia?
Pinia (发音为 /piːnjʌ/
,类似英文中的 “peenya”) 是最接近有效包名 piña (西班牙语中的 pineapple,即“菠萝”) 的词。 菠萝花实际上是一组各自独立的花朵,它们结合在一起,由此形成一个多重的水果。 与 Store 类似,每一个都是独立诞生的,但最终它们都是相互联系的。 它(菠萝)也是一种原产于南美洲的美味热带水果。
2.Pinia的使用
1.Pinia的安装:
1.命令行运行下面指令
yarn add pinia
# 或者使用 npm
npm install pinia
2.创建一个 pinia 实例 (根 store) 并将其传递给应用
相关代码如下:(main.ts/main.js中)
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')
2.Pinia的核心概念
store(仓库):Store (如 Pinia) 是一个保存状态和业务逻辑的实体,它并不与你的组件树绑定。换句话说,它承载着全局状态。它有点像一个永远存在的组件,每个组件都可以读取和写入它。它有三个概念,state、getter 和 action,我们可以假设这些概念相当于组件中的 data
、 computed
和 methods
。
3.Pinia的创建:
在src目录下创建名为store的文件夹,在文件夹下创建名为index.js的文件(使用ts开发则创建index.ts)
4.Pinia中store的初始化:
defineStore接收两个参数,第一个参数是该store仓库的id(唯一的),第二个是配置选项(有两种写法)
1.第一种方式:Option Store:
import {defineStore} from 'pinia'
export const usePersonStore = defineStore('personInfo', {
//相当于是data
state: () => {
return {
age:18
}
},
//相当于computed
getters:{
//getters里面的方法可以接收state为参数
inputMyAge:(state)=>{
return `我的年龄是:${state.age}`
}
},
//相当于是methods
actions:{
ageIncrease:()=>{
this.age++;
}
}
})
2.第二种方式:Setup Store:
这种方式中:
ref()
就是state
属性computed()
就是getters
function()
就是actions
import {defineStore} from 'pinia'
import {computed, ref} from "vue";
export const usePersonStore = defineStore('personInfo',()=>{
const age=ref(18)
const inputMyage=computed(()=>`我的年龄是:${age.value}`)
const ageIncrease=()=>{
age.value++
}
//这里要记得返回出去,否则外面拿不到
return {age,inputMyage,ageIncrease}
})
4.Pinia在页面中的使用
1.在组件中,使用如下代码对store进行引入
2.之后,我们将数据显示到页面
完整代码如下:
<template>
<div>
<div> {{personStore.age}} </div>
<div> {{personStore.inputMyage}} </div>
<button @click="add">点我让年龄+1</button>
</div>
</template>
<script setup lang="ts">
//@符号为src文件夹
import {usePersonStore} from "@/store";
const personStore = usePersonStore();
const add=()=>{
personStore.ageIncrease();
}
</script>
页面的显示效果如下:
但是我们发现,如果通过这样的方式的话,我们需要在插值语法中使用 personStore. 来访问personStore里面的数据,那么有没有其他方法可以简化这种写法呢?
当然是有的。
5.Pinia在页面中的使用的优化(简便写法):
我们可以通过es解构的方式直接从store中提取相关的state(ref),getters(computed),actions(function)。
相关代码如下:
<template>
<div>
<div> {{age}} </div>
<div> {{inputMyage}} </div>
<button @click="add">点我让年龄+1</button>
</div>
</template>
<script setup lang="ts">
//@符号为src文件夹
import {usePersonStore} from "@/store";
import {storeToRefs} from "pinia";
const personStore = usePersonStore();
// 注意这里使用了storeToRefs这个方法
const {age,inputMyage}=storeToRefs(personStore)
//这里不需要使用storeToRefs方法
const {ageIncrease}=personStore
const add=()=>{
ageIncrease();
}
</script>
如果使用了es的解构运算的方式来获取store的属性和方法的话,那么将不起作用,因为它破坏了响应性!!!
所以pinia提供了storeToRefs这个函数,让它可以变为响应式,不过注意只有state(ref),getters(computed)这两个需要使用该方法去定义,actions(function)直接去解构获得即可,不需要使用storeToRefs函数。
storeToRefs函数解析式,会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性