所有分类
  • 所有分类
  • Html5资源
  • React资源
  • Vue资源
  • Php资源
  • ‌小程序资源
  • Python资源

Vue Pinia 状态管理器入门教程

Pinia 是 Vue 的状态管理库,类似于 Vuex,但具有更简单的 API 和更好的性能。它提供了一种更简单、更灵活的方式来管理应用程序的状态。

1. 安装 Pinia

在 Vue 3 项目中安装 Pinia,可以使用 npm 或 yarn:

npm install pinia
# or
yarn add pinia

2. 基本使用

2.1 创建 Pinia 实例

在 main.js 文件中创建 Pinia 实例,并将其传递给 Vue 应用程序:

import { createApp } from "vue";
import { createPinia } from "pinia";
import App from "./App.vue";

const app = createApp(App);
const pinia = createPinia();

app.use(pinia);
app.mount("#app");

2.2 创建 Store

在 src 目录下创建一个 stores 目录,并在其中创建一个 store 文件,例如 user.js:

import { defineStore } from "pinia";

export const useUserStore = defineStore("user", {
  state: () => ({
    name: "",
    age: 0,
  }),
  actions: {
    setName(name) {
      this.name = name;
    },
    setAge(age) {
      this.age = age;
    },
  },
  getters: {
    fullName: (state) => `${state.name} ${state.age}`,
  },
});

2.3 使用 Store

在组件中使用 store,可以通过 useStore 函数来获取 store 实例:

import { useUserStore } from "@/stores/user";

const userStore = useUserStore();
userStore.name; // 访问 state
userStore.setName("zhang san"); // 调用 action
userStore.setAge(18); // 调用 action
userStore.fullName; // 访问 getter

3. 示例

3.1 订阅 $onAction

$onAction 用于订阅 store 中的 action 执行。它可以在 action 执行前、执行后或发生错误时进行拦截和处理。

3.1.1 日志记录

// stores/user.js
import { defineStore } from "pinia";

export const useUserStore = defineStore("user", {
  state: () => ({
    name: "",
    age: 0,
  }),
  actions: {
    async updateUserInfo(name, age) {
      this.name = name;
      this.age = age;
    },
  },
});

// 组件中
import { useUserStore } from "@/stores/user";

const userStore = useUserStore();

// 订阅所有 action
userStore.$onAction(
  ({
    name, // action 名称
    args, // 传递给 action 的参数数组
    store, // store 实例
    after, // action 执行后的钩子
    onError, // action 执行出错时的钩子
  }) => {
    // action 执行前的逻辑
    console.log(`Action ${name} started with args:`, args);

    // action 执行后的逻辑
    after((result) => {
      console.log(`Action ${name} completed with result:`, result);
    });

    // action 执行出错时的逻辑
    onError((error) => {
      console.error(`Action ${name} failed with error:`, error);
    });
  }
);

3.1.2 性能监控

const userStore = useUserStore();

userStore.$onAction(({ name, args, store, after }) => {
  const startTime = performance.now();

  after(() => {
    const endTime = performance.now();
    console.log(`Action ${name} took ${endTime - startTime}ms to execute`);
  });
});

3.1.3 错误处理和重试机制

// stores/user.js
export const useUserStore = defineStore("user", {
  state: () => ({
    name: "",
    age: 0,
  }),
  actions: {
    async fetchUserData() {
      // 模拟 API 调用
      const response = await fetch("/api/user");
      const data = await response.json();
      this.name = data.name;
      this.age = data.age;
    },
  },
});

// 组件中
const userStore = useUserStore();

userStore.$onAction(({ name, args, store, after, onError }) => {
  let retries = 0;
  const maxRetries = 3;

  onError(async (error) => {
    if (retries < maxRetries) {
      retries++;
      console.log(`Retrying action ${name}, attempt ${retries}`);
      await store.fetchUserData();
    } else {
      console.error(`Action ${name} failed after ${maxRetries} retries`);
    }
  });
});

3.1.4 权限控制

// stores/user.js
export const useUserStore = defineStore("user", {
  state: () => ({
    name: "",
    age: 0,
    role: "user",
  }),
  actions: {
    updateUserInfo(name, age) {
      this.name = name;
      this.age = age;
    },
    deleteUser() {
      // 删除用户的操作
    },
  },
});

// 在组件中使用
const userStore = useUserStore();

userStore.$onAction(({ name, args, store, after, onError }) => {
  // 检查权限
  if (name === "deleteUser" && store.role !== "admin") {
    onError(new Error("Permission denied"));
    return;
  }

  after(() => {
    console.log(`Action ${name} executed successfully`);
  });
});

3.1.5 取消订阅

$onAction 的返回值是一个函数,调用该函数可以取消订阅:

const unsubscribe = userStore.$onAction(({ name, after }) => {
  after(() => {
    console.log(`Action ${name} completed`);
  });
});

// 取消订阅
unsubscribe();

3.2 订阅 $subscribe

$subscribe 用于订阅 store 中的 state 变化。它可以在 state 变化时进行拦截和处理。

const userStore = useUserStore();

userStore.$subscribe((mutation, state) => {
  // mutation 是一个对象,包含以下属性:
  // type: 变化的类型,例如 "direct" 或 "patch"
  // storeId: store 的 ID
  // payload: 变化的 payload
  // 检查是否是 name 属性的变化
  if (
    mutation.type === "direct" &&
    mutation.storeId === "user" &&
    mutation.payload.name
  ) {
    // 同步 name 属性到其他地方
  }
});

3.3 $patch

$patch 用于批量更新 store 中的 state。它可以在一次操作中更新多个属性,而不需要逐个调用 set 方法。

const userStore = useUserStore();

userStore.$patch({
  name: "zhang san",
  age: 18,
});

3.4 $reset

$reset 用于重置 store 中的 state 到初始状态。它可以在需要重置 store 中的所有数据时使用。

const userStore = useUserStore();

userStore.$reset();

3.5 持久化 Store

// main.js
import { createPersistedState } from "pinia-plugin-persistedstate";
import { createPinia } from "pinia";

const pinia = createPinia();
pinia.use(createPersistedState());

app.use(pinia);
app.mount("#app");

// user.js
import { defineStore } from "pinia";

export const useUserStore = defineStore("user", {
  state: () => ({
    firstname: "",
    lastname: "",
  }),
  actions: {
    setFirstname(name) {
      this.firstname = name;
    },
    setLastname(name) {
      this.lastname = name;
    },
  },
  getters: {
    fullName: (state) => `${state.firstname} ${state.lastname}`,
    }
  },
  persist: true, // 启用持久化存储
});

3.6 路由守卫

// main.js
import { createRouter, createWebHistory } from "vue-router";
import { createPinia } from "pinia";
import { useUserStore } from "./stores/user";

const router = createRouter({
  history: createWebHistory(),
  routes: [
    // 路由配置
  ],
});

router.beforeEach((to, from, next) => {
  const userStore = useUserStore();
  if (to.meta.requiresAuth && !userStore.isAuthenticated) {
    next({ name: "login" });
  } else {
    next();
  }
});

const pinia = createPinia();
pinia.use(({ store }) => {
  store.$subscribe((mutation, state) => {
    if (mutation.type === "direct" && mutation.storeId === "user") {
      // 检查是否需要重新导航
      if (mutation.payload.isAuthenticated) {
        router.push({ name: "home" });
      }
    }
  });
});

app.use(router);
app.use(pinia);
app.mount("#app");

3.7 热更新

// main.js
import { createApp } from "vue";
import { createPinia, acceptHMRUpdate } from "pinia";
import App from "./App.vue";

const app = createApp(App);

const pinia = createPinia();
pinia.use(({ store }) => {
  store.$subscribe((mutation, state) => {
    if (mutation.type === "direct" && mutation.storeId === "user") {
      // 检查是否需要重新导航
      if (mutation.payload.isAuthenticated) {
        router.push({ name: "home" });
      }
    }
  });
});

if (import.meta.hot) {
  import.meta.hot.accept(acceptHMRUpdate(app, import.meta.hot));
}

app.use(pinia);
app.mount("#app");

原文链接:https://code.ifrontend.net/archives/323,转载请注明出处。
0

评论0

显示验证码
没有账号?注册  忘记密码?