• 【Pinia】Pinia的概念、优势及使用方式


    学习公司的项目,发现用到了Pinia,于是上网学习了一下,发现了一篇比较优秀的文章,于是将极少部分放到此记录学习,原文链接在末尾。

    是什么

    官网解释:

    Pinia 是 Vue 的存储库,它允许您跨组件/页面共享状态。

    从上面官网的解释不难看出,pinia和Vuex的作用是一样的,它也充当的是一个存储数据的作用,存储在pinia的数据允许我们在各个组件中使用。

    相较于vuex的优点

    Vue2和Vue3都支持,这让我们同时使用Vue2和Vue3的小伙伴都能很快上手。
    ●pinia中只有state、getter、action,抛弃了Vuex中的Mutation,Vuex中mutation一直都不太受小伙伴们的待见,pinia直接抛弃它了,这无疑减少了我们工作量。
    ●pinia中action支持同步和异步
    ●良好的Typescript支持,毕竟我们Vue3都推荐使用TS来编写,这个时候使用pinia就非常合适了
    ●无需再创建各个模块嵌套了,Vuex中如果数据过多,我们通常分模块来进行管理,稍显麻烦,而pinia中每个store都是独立的,互相不影响。
    ●体积非常小,只有1KB左右。 ●pinia支持插件来扩展自身功能。 ●支持服务端渲染。

    使用

    安装

    yarn add pinia
    //或者使用 npm
    npm install pinia
    
    • 1
    • 2
    • 3

    挂载

    // main.ts
    
    
    import { createApp } from "vue";
    import App from "./App.vue";
    import { createPinia } from "pinia";
    const pinia = createPinia();
    
    
    const app = createApp(App);
    app.use(pinia);
    app.mount("#app");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    创建某一模块相关的store

    /src/store/user.ts
    
    
    import { defineStore } from 'pinia'
    
    
    // 第一个参数是应用程序中 store 的唯一 id
    export const useUsersStore = defineStore('users', {
      // 其它配置项
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    创建store很简单,调用pinia中的defineStore函数即可,该函数接收两个参数:
    ●name:一个字符串,必传项,该store的唯一id。
    ●options:一个对象,store的配置项,比如配置store内的数据,修改数据的方法等等。
    我们可以定义任意数量的store,因为我们其实一个store就是一个函数,这也是pinia的好处之一,让我们的代码扁平化了,这和Vue3的实现思想是一样的。

    使用该store

    /src/App.vue
    
    <script setup lang="ts">
    import { useUsersStore } from "../src/store/user";
    const store = useUsersStore();
    console.log(store);
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用store很简单,直接引入我们声明的useUsersStore 方法即可,我们可以先看一下执行该方法输出的是什么:

    添加state

    我们需要存放的数据就放在options对象中的state属性内。
    假设我们往store添加一些任务基本数据,修改user.ts代码。

    /src/store/user.ts
    
    import { defineStore } from 'pinia'
    
    
    export const useUsersStore = defineStore("users", {
      state: () => {
        return {
          name: "小猪课堂",
          age: 25,
          sex: "男",
        };
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    读取state

    修改App.vue,通过解构赋值拿取数据,并让这几个数据显示出来。
    注意:需要利用pinia的storeToRefs函数,将state中的数据变为响应式。

    <template>
      <img alt="Vue logo" src="./assets/logo.png" />
      <p>姓名:{{ name }}</p>
      <p>年龄:{{ age }}</p>
      <p>性别:{{ sex }}</p>
    </template>
    <script setup lang="ts">
    import { ref } from "vue";
    import { useUsersStore } from "../src/store/user";
    import { storeToRefs } from 'pinia';
    const store = useUsersStore();
    const { name, age, sex } = storeToRefs(store);
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    结果:
    在这里插入图片描述

    修改state

    <template>
      <h1>我是child组件</h1>
      <p>姓名:{{ name }}</p>
      <p>年龄:{{ age }}</p>
      <p>性别:{{ sex }}</p>
      <button @click="changeName">更改姓名</button>
    </template>
    <script setup lang="ts">
    import { useUsersStore } from "../src/store/user";
    import { storeToRefs } from 'pinia';
    const store = useUsersStore();
    const { name, age, sex } = storeToRefs(store);
    const changeName = () => {
      store.name = "小猪课堂";
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    重置state

    有时候我们修改了state数据,想要将它还原,比如用户填写了一部分表单,突然想重置为最初始的状态。

    <button @click="reset">重置store</button>
    // 重置store
    const reset = () => {
      store.$reset();
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    批量更改state数据

    store.$patch((state) => {
      state.items.push({ name: 'shoes', quantity: 1 })
      state.hasChanged = true
    })
    
    • 1
    • 2
    • 3
    • 4

    替换整个state

    store.$state = { counter: 666, name: '张三' }
    
    • 1

    添加getter

    export const useUsersStore = defineStore("users", {
      state: () => {
        return {
          name: "小猪课堂",
          age: 25,
          sex: "男",
        };
      },
      getters: {
        getAddAge: (state) => {
          return state.age + 100;
        },
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    使用getter

    <template>
      <p>新年龄:{{ store.getAddAge }}</p></template>
    <script setup lang="ts">
    import { useUsersStore } from "../src/store/user";
    const store = useUsersStore();
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    直接在标签上使用了store.gettAddAge方法,这样可以保证响应式

    getter中调用其它getter

    export const useUsersStore = defineStore("users", {
      state: () => {
        return {
          name: "小猪课堂",
          age: 25,
          sex: "男",
        };
      },
      getters: {
        getAddAge: (state) => {
          return state.age + 100;
        },
        getNameAndAge(): string {
          return this.name + this.getAddAge; // 调用其它getter
        },
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    getter传参

    export const useUsersStore = defineStore("users", {
      state: () => {
        return {
          name: "小猪课堂",
          age: 25,
          sex: "男",
        };
      },
      getters: {
        getAddAge: (state) => {
          return (num: number) => state.age + num;
        },
        getNameAndAge(): string {
          return this.name + this.getAddAge; // 调用其它getter
        },
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
     <p>新年龄:{{ store.getAddAge(1100) }}p>
    
    • 1

    添加actions

    export const useUsersStore = defineStore("users", {
      state: () => {
        return {
          name: "小猪课堂",
          age: 25,
          sex: "男",
        };
      },
        actions: {
        saveName(name: string) {
          this.name = name;
        },
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    使用actions

    //app.vue
    const saveName = () => {
      store.saveName("我是小猪");
    };
    
    • 1
    • 2
    • 3
    • 4

    汇总代码

    main.ts代码:

    import { createApp } from "vue";
    import App from "./App.vue";
    import { createPinia } from "pinia";
    const pinia = createPinia();
    
    
    const app = createApp(App);
    app.use(pinia);
    app.mount("#app");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    user.ts代码:

    import { defineStore } from "pinia";
    
    
    // 第一个参数是应用程序中 store 的唯一 id
    export const useUsersStore = defineStore("users", {
      state: () => {
        return {
          name: "小猪课堂",
          age: 25,
          sex: "男",
        };
      },
      getters: {
        getAddAge: (state) => {
          return (num: number) => state.age + num;
        },
        getNameAndAge(): string {
          return this.name + this.getAddAge; // 调用其它getter
        },
      },
      actions: {
        saveName(name: string) {
          this.name = name;
        },
      },
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    App.vue代码:

    <template>
      <img alt="Vue logo" src="./assets/logo.png" />
      <p>姓名:{{ name }}</p>
      <p>年龄:{{ age }}</p>
      <p>性别:{{ sex }}</p>
      <p>新年龄:{{ store.getAddAge(1100) }}</p>
      <p>调用其它getter:{{ store.getNameAndAge }}</p>
      <button @click="changeName">更改姓名</button>
      <button @click="reset">重置store</button>
      <button @click="patchStore">批量修改数据</button>
      <button @click="saveName">调用aciton</button>
    
    
      <!-- 子组件 -->
      <child></child>
    </template>
    <script setup lang="ts">
    import child from "./child.vue";
    import { useUsersStore } from "../src/store/user";
    import { storeToRefs } from "pinia";
    const store = useUsersStore();
    const { name, age, sex } = storeToRefs(store);
    const changeName = () => {
      store.name = "张三";
      console.log(store);
    };
    // 重置store
    const reset = () => {
      store.$reset();
    };
    // 批量修改数据
    const patchStore = () => {
      store.$patch({
        name: "张三",
        age: 100,
        sex: "女",
      });
    };
    // 调用actions方法
    const saveName = () => {
      store.saveName("我是小猪");
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    原文:
    大菠萝!这一次彻底搞懂Pinia!(保姆级教程)

  • 相关阅读:
    园子的脱困努力-云厂商合作:领取阿里云免费ECS试用资源,部署Java Web环境,送小礼品
    学习 C++ 到底有什么好处?
    Hazelcast系列(一):初识hazelcast
    管理类联考——数学——汇总篇——知识点突破——代数——函数、方程——记忆
    Outlook 教程,如何在 Outlook 中使用颜色类别和提醒?
    如何记录分析你的炼丹流程—可视化神器Wandb使用笔记【1】
    GPU架构变迁之AI系统视角:从费米到安培
    Unity UI Toolkit学习笔记-EditorWindow
    数据一致性:核心概念与实现策略
    Java项目:音乐专辑商城系统(java+SSM+JSP+jQuery+Mysql)
  • 原文地址:https://blog.csdn.net/fangyuan__/article/details/132991447