简记Vue3(五)—— Pinia
个人简介
👀个人主页: 前端杂货铺
🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展
📃个人状态: 研发工程师,现效力于中国工业软件事业
🚀人生格言: 积跬步至千里,积小流成江海
🥇推荐学习:🍍前端面试宝典 🎨100个小功能 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧
文章目录
- 前言
- pinia
前言
重拾 Vue3,查缺补漏、巩固基础。
pinia
pinia 是一个状态管理库,类似于 Vue2 对应的状态管理库 Vuex。
先安装几个插件,便于后续编码。
// 发请求
yarn add axios
// 生成唯一id
yarn add nanoid
// pinia状态管理库
yarn add pinia
使用 pinia 时,我们通常把用于状态管理的文件放入 ./store
文件夹中,如下图所示。
在 main.ts
中使用 pinia。
import { createApp } from "vue";
import App from "./App.vue";
import { createPinia } from "pinia";
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount("#app");
我们在 App.vue
组件中引入 Count.vue
和 LoveTalk.vue
组件并使用。
<template>
<Count></Count>
<hr />
<LoveTalk></LoveTalk>
</template>
<script setup lang="ts">
import Count from "./components/Count.vue";
import LoveTalk from "./components/LoveTalk.vue";
</script>
在 Count.vue
组件中进行数字的运算操作。
- 使用 store 里的东西需要先引入一下,如下面代码的
useCountStore()
- 使用解构的方式从
countStore
里面取东西时需要使用storeToRefs
,用于 state 中的数据不丢失响应式 - 使用
$patch
可以实现批量修改数据,此时只会重新渲染一次 DOM (性能比较好)
<template>
<div>
<h2>当前求和为:{{ sum }}</h2>
<h2>放大十倍:{{ bigSum }}</h2>
<h2>缩小十倍:{{ smallSum }}</h2>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="add">加</button>
<button @click="minus">减</button>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import { useCountStore } from "../store/count";
import { storeToRefs } from "pinia";
const countStore = useCountStore();
// storeToRefs 只会关注 state 中的数据,不会对方法进行 ref 包裹
const { sum, bigSum, smallSum } = storeToRefs(countStore);
let n = ref(1); // 用户选择的数学
function add() {
// 第一种修改方式
// countStore.sum += n.value;
// 第二种修改方式,可以批量修改数据
// countStore.$patch({
// sum: countStore.sum + n.value,
// });
// 第三种修改方式,调用 actions 中的函数
countStore.increment(n.value);
}
function minus() {
countStore.sum -= n.value;
}
</script>
我们在 ./store/count.ts
文件中对 count.vue 组件需要使用的数据进行存储管理。
- 首先要从 pinia 中引入
defineStore
,用于定义 defineStore
接收两个参数,第一个参数用来标识 store,第二个参数是一个对象,用于存储和管理数据- state 存储数据相当于 data
- actions 中编写方法相当于 methods
- getters 中处理和计算 state 中的属性相当于 computed
import { defineStore } from "pinia";
export const useCountStore = defineStore("count", {
actions: {
increment(value: number) {
this.sum += value;
},
},
// 存储数据的地方
state() {
return {
sum: 6,
};
},
getters: {
// 通过 this 获取 sum
bigSum(): number {
return this.sum * 10;
},
// 通过 state 传参获取 sum
smallSum: (state) => {
return state.sum / 10;
},
},
});
同样的,我们在 LoveTalk.vue
中来两句土味情话。
- 通过
storeToRefs
响应式的接收 talkList 数据 - 使用
$subscribe
进行订阅,它主要用于监听状态的变化,并在状态发生变化时触发相应的回调函数(用途:登录后存储用户信息、数据持久化等)
<template>
<div>
<button @click="getLoveTalk">获得一句话</button>
<ul>
<li v-for="talk in talkList" :key="talk.id">
{{ talk.title }}
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import { reactive } from "vue";
import { storeToRefs } from "pinia";
import { useLoveTalkStore } from "../store/loveTalk";
const loveTalkStore = useLoveTalkStore();
const { talkList } = storeToRefs(loveTalkStore);
// 订阅 => 在此可以进行一些浏览器存储数据的操作
loveTalkStore.$subscribe((mutate, state) => {
console.log("loveTalkStore里面的数据发生了变换", loveTalkStore);
});
function getLoveTalk() {
loveTalkStore.getATalk();
}
</script>
在 ./store/loveTalk.ts
文件中进行相关数据的存储和操作
- 注释部分是选项时写法,非注释部分为组合式写法(推荐,但记得 return 出去)
import { defineStore } from "pinia";
import axois from "axios";
import { nanoid } from "nanoid";
// 选项式写法
// export const useLoveTalkStore = defineStore("talk", {
// actions: {
// async getATalk() {
// // 解构赋值 + 重命名
// let {
// data: { content: title },
// } = await axois.get("https://api.uomg.com/api/rand.qinghua?format=json");
// let obj = { id: nanoid(), title };
// this.talkList.unshift(obj);
// },
// },
// state() {
// return {
// talkList: [
// { id: "1", title: "张三" },
// { id: "2", title: "法外狂徒" },
// { id: "3", title: "罗老师" },
// ],
// };
// },
// });
// 组合式写法
import { reactive } from "vue";
export const useLoveTalkStore = defineStore("talk", () => {
const talkList = reactive([
{ id: "1", title: "你好" },
{ id: "2", title: "我..." },
{ id: "3", title: "你懂的" },
]);
async function getATalk() {
// 解构赋值 + 重命名
let {
data: { content: title },
} = await axois.get("https://api.uomg.com/api/rand.qinghua?format=json");
let obj = { id: nanoid(), title };
talkList.unshift(obj);
}
// 记得 return
return { talkList, getATalk };
});
以上是 pinia 的基本使用,对于详情内容请参阅 Pinia中文文档
参考资料:
https://www.bilibili.com/video/BV1Za4y1r7KE?spm_id_from=333.788.videopod.episodes&vd_source=f839085517d2b7548b2939bfe214d466&p=51