第Ⅶ章-Ⅱ Pinia详解

简介

Pinia 是 Vue 3 官方推荐的状态管理库,也是 Vuex 的替代方案之一。它更轻量、更现代化,并提供更好的 TypeScript 支持。

安装 Pinia

首先,确保你已经安装了Vue3 并且初始化了项目。
npm

npm install pinia

yarn

yarn add pinia

配置Pinia

在 main.ts 中创建并配置 Pinia

// src/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');

定义Store

在 src/stores 目录中创建 store 文件,比如 counter.ts。

// src/stores/counter.ts
import { defineStore } from 'pinia';

// 使用 TypeScript 接口定义状态类型
interface CounterState {
  count: number;
}

// 定义 store
export const useCounterStore = defineStore({
  id: 'counter',
  state: (): CounterState => ({
    count: 0
  }),
  getters: {
    doubleCount: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++;
    },
    decrement() {
      this.count--;
    },
    incrementBy(amount: number) {
      this.count += amount;
    }
  }
});

组件中使用

<!-- src/components/CounterComponent.vue -->
<template>
  <div>
    <h2>Counter</h2>
    <p>Count: {{ store.count }}</p>
    <p>Double Count: {{ store.doubleCount }}</p>
    <button @click="store.increment">Increment</button>
    <button @click="store.decrement">Decrement</button>
    <button @click="incrementBy(5)">Increment by 5</button>
  </div>
</template>

<script setup lang="ts">
import { useCounterStore } from '@/stores/counter';

const store = useCounterStore();

const incrementBy = (amount: number) => {
  store.incrementBy(amount);
};
</script>

处理异步操作

// src/stores/counter.ts
import { defineStore } from 'pinia';

interface CounterState {
  count: number;
}

export const useCounterStore = defineStore({
  id: 'counter',
  state: (): CounterState => ({
    count: 0
  }),
  getters: {
    doubleCount: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++;
    },
    decrement() {
      this.count--;
    },
    incrementBy(amount: number) {
      this.count += amount;
    },
    async incrementAsync(amount: number) {
      // 模拟异步操作
      return new Promise<void>((resolve) => {
        setTimeout(() => {
          this.incrementBy(amount);
          resolve();
        }, 1000);
      });
    }
  }
});

组件中使用异步操作

<!-- src/components/CounterComponent.vue -->
<template>
  <div>
    <h2>Counter</h2>
    <p>Count: {{ store.count }}</p>
    <p>Double Count: {{ store.doubleCount }}</p>
    <button @click="store.increment">Increment</button>
    <button @click="store.decrement">Decrement</button>
    <button @click="incrementBy(5)">Increment by 5</button>
    <button @click="incrementAsync(3)">Increment by 3 (Async)</button>
  </div>
</template>

<script setup lang="ts">
import { useCounterStore } from '@/stores/counter';

const store = useCounterStore();

const incrementBy = (amount: number) => {
  store.incrementBy(amount);
};

const incrementAsync = async (amount: number) => {
  await store.incrementAsync(amount);
};
</script>

模块化Store

Pinia 通过 defineStore 函数实现模块化 Store,每个 Store 都是一个独立的模块。
定义用户Store

// src/stores/user.ts
import { defineStore } from 'pinia';

interface UserState {
  name: string;
  age: number;
}

export const useUserStore = defineStore({
  id: 'user',
  state: (): UserState => ({
    name: 'Alice',
    age: 25
  }),
  getters: {
    isAdult: (state) => state.age >= 18
  },
  actions: {
    updateName(newName: string) {
      this.name = newName;
    },
    incrementAge() {
      this.age++;
    }
  }
});

使用持久化插件

如果希望 Pinia 的状态在刷新后保持不变,可以使用 pinia-plugin-persistedstate 插件。

npm install pinia-plugin-persistedstate

配置持久化插件

// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';

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

const app = createApp(App);
app.use(pinia);
app.mount('#app');

使用持久化插件,在需要持久化的 Store 中添加 persist 选项

// src/stores/user.ts
import { defineStore } from 'pinia';

interface UserState {
  name: string;
  age: number;
}

export const useUserStore = defineStore({
  id: 'user',
  state: (): UserState => ({
    name: 'Alice',
    age: 25
  }),
  getters: {
    isAdult: (state) => state.age >= 18
  },
  actions: {
    updateName(newName: string) {
      this.name = newName;
    },
    incrementAge() {
      this.age++;
    }
  },
  persist: {
    enabled: true
  }
});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值