Vue学习笔记(十二)

5. pinia

5.1【准备一个效果】

20241102192659

5.2【搭建 pinia 环境】

第一步:npm install pinia

第二步:操作 src/main.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { createApp } from "vue";
import App from "./App.vue";

/* 引入createPinia,用于创建pinia */
import { createPinia } from "pinia";

/* 创建pinia */
const pinia = createPinia();
const app = createApp(App);

/* 使用插件 */ {
}
app.use(pinia);
app.mount("#app");

此时开发者工具中已经有了 pinia选项

20241102192715

5.3【存储+读取数据】

  1. Store是一个保存:状态业务逻辑 的实体,每个组件都可以读取写入它。

  2. 它有三个概念:stategetteraction,相当于组件中的: datacomputedmethods

  3. 具体编码:src/store/count.ts

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    // 引入defineStore用于创建store
    import { defineStore } from "pinia";

    // 定义并暴露一个store
    export const useCountStore = defineStore("count", {
    // 动作
    actions: {},
    // 状态
    state() {
    return {
    sum: 6,
    };
    },
    // 计算
    getters: {},
    });
  4. 具体编码:src/store/talk.ts

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 引入defineStore用于创建store
    import { defineStore } from "pinia";

    // 定义并暴露一个store
    export const useTalkStore = defineStore("talk", {
    // 动作
    actions: {},
    // 状态
    state() {
    return {
    talkList: [
    { id: "yuysada01", content: "你今天有点怪,哪里怪?怪好看的!" },
    { id: "yuysada02", content: "草莓、蓝莓、蔓越莓,你想我了没?" },
    { id: "yuysada03", content: "心里给你留了一块地,我的死心塌地" },
    ],
    };
    },
    // 计算
    getters: {},
    });
  5. 组件中使用 state中的数据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <template>
    <h2>当前求和为:{{ sumStore.sum }}</h2>
    </template>

    <script setup lang="ts" name="Count">
    // 引入对应的useXxxxxStore
    import { useSumStore } from "@/store/sum";

    // 调用useXxxxxStore得到对应的store
    const sumStore = useSumStore();
    </script>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <template>
    <ul>
    <li v-for="talk in talkStore.talkList" :key="talk.id">
    {{ talk.content }}
    </li>
    </ul>
    </template>

    <script setup lang="ts" name="Count">
    import axios from "axios";
    import { useTalkStore } from "@/store/talk";

    const talkStore = useTalkStore();
    </script>

5.4.【修改数据】(三种方式)

  1. 第一种修改方式,直接修改

    1
    countStore.sum = 666;
  2. 第二种修改方式:批量修改

    1
    2
    3
    4
    countStore.$patch({
    sum: 999,
    school: "atguigu",
    });
  3. 第三种修改方式:借助 action修改(action中可以编写一些业务逻辑)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    import { defineStore } from "pinia";

    export const useCountStore = defineStore("count", {
    /*************/
    actions: {
    //加
    increment(value: number) {
    if (this.sum < 10) {
    //操作countStore中的sum
    this.sum += value;
    }
    },
    //减
    decrement(value: number) {
    if (this.sum > 1) {
    this.sum -= value;
    }
    },
    },
    /*************/
    });
  4. 组件中调用 action即可

    1
    2
    3
    4
    5
    // 使用countStore
    const countStore = useCountStore();

    // 调用对应action
    countStore.incrementOdd(n.value);

5.5.【storeToRefs】

  • 借助 storeToRefsstore中的数据转为 ref对象,方便在模板中使用。
  • 注意:pinia提供的 storeToRefs只会将数据做转换,而 VuetoRefs会转换 store中数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div class="count">
<h2>当前求和为:{{ sum }}</h2>
</div>
</template>

<script setup lang="ts" name="Count">
import { useCountStore } from "@/store/count";
/* 引入storeToRefs */
import { storeToRefs } from "pinia";

/* 得到countStore */
const countStore = useCountStore();
/* 使用storeToRefs转换countStore,随后解构 */
const { sum } = storeToRefs(countStore);
</script>

5.6.【getters】

  1. 概念:当 state中的数据,需要经过处理后再使用时,可以使用 getters配置。

  2. 追加 getters配置。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // 引入defineStore用于创建store
    import { defineStore } from "pinia";

    // 定义并暴露一个store
    export const useCountStore = defineStore("count", {
    // 动作
    actions: {
    /************/
    },
    // 状态
    state() {
    return {
    sum: 1,
    school: "atguigu",
    };
    },
    // 计算
    getters: {
    bigSum: (state): number => state.sum * 10,
    upperSchool(): string {
    return this.school.toUpperCase();
    },
    },
    });
  3. 组件中读取数据:

    1
    2
    const { increment, decrement } = countStore;
    let { sum, school, bigSum, upperSchool } = storeToRefs(countStore);

5.7.【$subscribe】

通过 store 的 $subscribe() 方法侦听 state 及其变化

1
2
3
4
talkStore.$subscribe((mutate, state) => {
console.log("LoveTalk", mutate, state);
localStorage.setItem("talk", JSON.stringify(talkList.value));
});

5.8. 【store 组合式写法】

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import { defineStore } from "pinia";
import axios from "axios";
import { nanoid } from "nanoid";
import { reactive } from "vue";

export const useTalkStore = defineStore("talk", () => {
// talkList就是state
const talkList = reactive(
JSON.parse(localStorage.getItem("talkList") as string) || []
);

// getATalk函数相当于action
async function getATalk() {
// 发请求,下面这行的写法是:连续解构赋值+重命名
let {
data: { content: title },
} = await axios.get("https://api.uomg.com/api/rand.qinghua?format=json");
// 把请求回来的字符串,包装成一个对象
let obj = { id: nanoid(), title };
// 放到数组中
talkList.unshift(obj);
}
return { talkList, getATalk };
});