【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 的创建和基本使用就完成了!

相关推荐
qianmoQ12 分钟前
第五章:工程化实践 - 第三节 - Tailwind CSS 大型项目最佳实践
前端·css
尚学教辅学习资料21 分钟前
基于SpringBoot+vue+uniapp的智慧旅游小程序+LW示例参考
vue.js·spring boot·uni-app·旅游
椰果uu27 分钟前
前端八股万文总结——JS+ES6
前端·javascript·es6
微wx笑1 小时前
chrome扩展程序如何实现国际化
前端·chrome
~废弃回忆 �༄1 小时前
CSS中伪类选择器
前端·javascript·css·css中伪类选择器
CUIYD_19891 小时前
Chrome 浏览器(版本号49之后)‌解决跨域问题
前端·chrome
IT、木易1 小时前
跟着AI学vue第五章
前端·javascript·vue.js
薛定谔的猫-菜鸟程序员1 小时前
Vue 2全屏滚动动画实战:结合fullpage-vue与animate.css打造炫酷H5页面
前端·css·vue.js
春天姐姐2 小时前
vue3项目开发总结
前端·vue.js·git
谢尔登2 小时前
【React】React 性能优化
前端·react.js·性能优化