【Vue.js】Pinia 的基本认识和使用

什么是 Pinia ?

官方描述:Pinia 是一款符合直觉的 Vue.js 状态管理库,它允许你跨组件或页面共享状态。

Pinia 的优势是什么?

  • Devtools 支持

    • 追踪状态变化的时间线,并及时给予开发者反馈
    • 配合 Vue DevTools, 可以在组件中展示所用到的 Pinia Store
    • 让调试更容易的 Time travel
  • HMR 热更新

    • 不必重载页面即可修改 Store
    • 开发时可保持当前的 State
  • 自定义插件:可通过插件扩展 Pinia 功能

  • TypeScript 支持

    • 为 JS 开发者提供适当的 TypeScript 支持以及自动补全功能。
  • 支持服务端渲染

    • Pinia 不仅仅能在 SPA 应用中使用,而且在 SSR 应用 (比如 Nuxt.js)也能够运用

PiniaVuex 的对比:

PiniaVuex 都是 Vue.js 的状态管理仓库(容器),但是在设计理念上面,VuexPinia 有所不同:

  1. 是否遵循 Flux流思想:Vuex 的设计是参照了 Flux 思想进行设计的 (state 管理状态,actions 派发任务,mutations 更新 state,state 变化重新渲染视图);但是 Pinia 取消掉了 Flux 这一繁琐的操作流程,直接使用单向数据流修改(state 管理状态,actions 更改 state,state 变化重新渲染视图)

  2. 基于第一点, PiniaVuex继承 DevTool 的位置不同:Pinia的 state 变化是在 actions 中监听的,Vuex的 state 的变化是在 actions 中监听的

  3. 核心模块的理念不同:

    • Vuex的设计是基本遵循单一 store 的思想,而 Pinia允许你的项目存在多个 store,并且由 pinia 统一管理这些 store
    • Vuex 实现多模块的方式是 module 嵌套,而 Pinia实现多模块的方式是多个扁平化的 store 。
    • 相比之下,Pinia 更加便捷,因为它无需再考虑是否需要配置 modules 和开启 namespaced
  4. 配置项不同:Vuex的配置更倾向于 Options API 风格;而 Pinia的包容性更强,它既可以使用 Options API 定义,也可以使用 Setup 函数 (Composition API)进行定义

  5. 对于 TypeScript 的支持:Pinia 的支持程度更好,因为它一开始就是用 TypeScript 进行开发的,没有历史包袱。

Pinia 的基本使用:

概述:

使用 Pinia 总共有三步:

  1. 让 VueApp (Vue 实例) 使用上 pinia 实例
  2. 定义创建获取 PiniaStore 的 Hook
  3. 在组件中使用创建 PiniaStore 的 Hook创建一个 Store,直接使用即可

代码演示:

1. 让 VueApp (Vue 实例) 使用上 pinia 实例

js 复制代码
import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';

const vueApp = createApp(App);

vueApp.use(createPinia());

vueApp.mount('#app');

2. 定义创建 PiniaStore 的 Hook

  • 选项式创建
js 复制代码
import { defineStore } from 'pinia';

const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  getters: {
    doubleCount() {
      return this.count * 2;
    }
  },
  actions: {
    addCount() {
      this.count += 1;
    }
  }
});

export default useCounterStore;
  • 组合式创建
js 复制代码
import { ref, computed } from 'vue';
import { defineStore } from 'pinia';

const useTodoListStore = defineStore('todoList', () => {
	const todoList = ref([]);

  const todoListCount = computed(() => todoList.value.length);

	function addTodo(todo) {
    if (!todo) {
      return;
    }
    todoList.value = [todo, ...todoList.value];
  }

  function removeTodo(id) {
    todoList.value = todoList.value.filter(item => item.id !== id);
  }

  function toggleTodo(id) {
    todoList.value = todoList.value.map(item => {
      if (item.id === id) {
        item.completed = !item.completed;
      }

      return item;
    });
  }
  
  return {
    todoList,
    todoListCount,

    addTodo,
    removeTodo,
    toggleTodo,
  };
});

export default useTodoListStore;

3. 在组件中使用创建 PiniaStore 的 Hook创建一个 Store,直接使用即可

html 复制代码
<script setup>
	import { ref } from 'vue';
  
  import useCounterStore from '@/store/counterStore';
  import useTodoListStore from '@/store/todoListStore';

  const counterStore = useCounterStore();
  const todoListStore = useTodoListStore();

  const addTodoInput = ref('');

  function handleAddTodoBtnClick() {
    const content = addTodoInput.value.trim();

    if (!content) {
      return;
    }

    const todo = {
      content,
      id: new Date().getTime(),
      completed: false
    };
    todoListStore.addTodo(todo);
  }
</script>

<template>
  <div class="container">
    <div class="counter">
      <h1>{{ counterStore.count }}</h1>
      <button @click="counterStore.addCount">ADD COUNT</button>
    </div>
    <hr />
    <div class="todo-list">
      <div class="add-todo-input">
        <input v-model="addTodoInput" placeholder="请输入待办项" />
        <button @click="handleAddTodoBtnClick">添加待办项</button>
      </div>
      <ul class="list">
        <li
          class="list-item"
          v-for="item of todoListStore.todoList"
          :key="item.id"
        >
          <input
            type="checkbox"
            :checked="item.completed"
            @click="todoListStore.toggleTodo(item.id)"
          />
          <span :style="{ textDecoration: item.completed ? 'line-through' : '' }">
            {{ item.content }}
          </span>
          <button @click="todoListStore.removeTodo(item.id)">
            REMOVE TODO
          </button>
        </li>
      </ul>
    </div>
  </div>
</template>

像这样,Pinia 的创建和基本使用就完成了!

相关推荐
恋猫de小郭27 分钟前
对于普通程序员来说 AI 是什么?AI 究竟用的是什么?
前端·flutter·ai编程
大怪v1 小时前
前端:人工智能?我也会啊!来个花活,😎😎😎“自动驾驶”整起!
前端·javascript·算法
我是天龙_绍1 小时前
vue3 props 如何写ts,进行类型标注
前端
叫我詹躲躲1 小时前
n8n 自动化工作流平台完整部署
前端·langchain·领域驱动设计
遂心_3 小时前
为什么 '1'.toString() 可以调用?深入理解 JavaScript 包装对象机制
前端·javascript
IT_陈寒3 小时前
JavaScript 性能优化:5 个被低估的 V8 引擎技巧让你的代码快 200%
前端·人工智能·后端
王同学QaQ3 小时前
Vue3对接UE,通过MQTT完成通讯
javascript·vue.js
岛风风3 小时前
关于手机的设备信息
前端
ReturnTrue8683 小时前
nginx性能优化之Gzip
前端
华仔啊3 小时前
基于 RuoYi-Vue 轻松实现单用户登录功能,亲测有效
java·vue.js·后端