Vue3 之 Pinia 核心概念(八)

作者 : admin 本文共3894个字,预计阅读时间需要10分钟 发布时间: 2024-06-16 共1人阅读

核心概念

State:这是你的应用程序的状态,是一个响应式的对象。
Getters:类似于 Vuex 中的 getters,它们是基于 state 的计算属性。
Actions:类似于 Vuex 中的 mutations 和 actions,它们用于改变 state。但与 Vuex 不同的是,在 Pinia 中,mutations 和 actions 被合并为一个概念,即 actions。
其他特性:Pinia 还支持插件、热重载、服务器端渲染等。

安装

npm install pinia  
# 或者使用 yarn  
yarn add pinia

main.js

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')

store/counter.js

import { defineStore } from 'pinia'  
  
export const useCounterStore = defineStore('counter', {  
  // state  
  state: () => ({  
    count: 0,  
  }),  
  
  // getters  
  getters: {  
    doubleCount: (state) => state.count * 2,  
  },  
  
  // actions  
  actions: {  
    increment() {  
      this.count++  
    },  
  
    decrement() {  
      this.count--  
    },  
  
    // 你也可以在 actions 中使用其他 actions 或 getters  
    incrementBy(amount) {  
      this.count += amount  
    },  
  },  
})

App.vue

<template>  
  <div>  
    <p>Count: {{ counterStore.count }}</p>  
    <p>Double Count: {{ counterStore.doubleCount }}</p>  
    <button @click="counterStore.increment">Increment</button>  
    <button @click="counterStore.decrement">Decrement</button>  
    <button @click="counterStore.incrementBy(5)">Increment by 5</button>  
  </div>  
</template>  
  
<script>  
import { useCounterStore } from './store/counter'  
  
export default {  
  setup() {  
    const counterStore = useCounterStore()  
    return { counterStore }  
  },  
}  
</script>

扩展 Store

由于有了底层 API 的支持,Pinia store 现在完全支持扩展。以下是你可以扩展的内容:

为 store 添加新的属性
定义 store 时增加新的选项
为 store 增加新的方法
包装现有的方法
改变甚至取消 action
实现副作用,如本地存储
仅应用插件于特定 store

1. 插件 (Plugins)

插件是通过 pinia.use() 添加到 pinia 实例的。最简单的例子是通过返回一个对象将一个静态属性添加到所有 store。

import { createPinia } from 'pinia'

// 创建的每个 store 中都会添加一个名为 `secret` 的属性。
// 在安装此插件后,插件可以保存在不同的文件中
function SecretPiniaPlugin() {
  return { secret: 'the cake is a lie' }
}

const pinia = createPinia()
// 将该插件交给 Pinia
pinia.use(SecretPiniaPlugin)

// 在另一个文件中
const store = useStore()
store.secret // 'the cake is a lie'

2. 持久化状态 (Persistence)
代码示例(使用第三方插件 pinia-plugin-persistedstate):

npm install pinia-plugin-persistedstate
import { createApp } from 'vue';  
import { createPinia } from 'pinia';  
import createPersistedState from 'pinia-plugin-persistedstate';  
  
const pinia = createPinia();  
  
// 使用插件  
pinia.use(createPersistedState({  
  storage: window.localStorage,  
}));  
  
const app = createApp(/* ... */);  
app.use(pinia);  
// ...

3. 订阅状态变化 (Subscribing to State Changes)
Pinia 允许你订阅 Store 的状态变化,以便在状态更新时执行某些操作。这可以通过 pinia.state.subscribe 方法实现。
代码示例(在插件中使用):

// 插件中的代码  
app.pinia.state.subscribe((mutation, state) => {  
  // mutation 是一个对象,包含 type('direct' 或 'patch')和 key  
  // state 是 Store 的当前状态  
  console.log('State mutated:', mutation, state);  
});

4. 使用 TypeScript 进行类型安全
如果你在使用 TypeScript,Pinia 提供了强大的类型支持,确保你的代码是类型安全的。你可以为 state、getters 和 actions 提供类型定义。

代码示例(使用 TypeScript):

import { defineStore } from 'pinia';  
  
interface CounterState {  
  count: number;  
}  
  
export const useCounterStore = defineStore('counter', {  
  state: (): CounterState => ({  
    count: 0,  
  }),  
  // ...  
});

5. 访问其他 Store
在 Pinia 中,一个 Store 可以很容易地访问另一个 Store 的状态和方法。你可以直接在 Store 的 actions 中使用 useStore 函数来访问其他 Store。

代码示例:

import { defineStore } from 'pinia';  
import { useOtherStore } from './otherStore';  
  
export const useCounterStore = defineStore('counter', {  
  // ...  
  actions: {  
    incrementAndDoSomethingElse() {  
      this.count++;  
      const otherStore = useOtherStore();  
      otherStore.doSomething();  
    },  
  },  
});

在组件外部使用 Store

1. 创建 Pinia 实例和 Store
首先,你需要在你的主入口文件(如 main.js 或 main.ts)中创建 Pinia 实例,并使用它创建你的 Store。

// main.js  
import { createApp } from 'vue'  
import { createPinia } from 'pinia'  
import App from './App.vue'  
  
const app = createApp(App)  
const pinia = createPinia()  
  
// 使用 Pinia  
app.use(pinia)  
  
// 挂载应用  
app.mount('#app')  
  
// 假设你有一个名为 useCounterStore 的 Store  
// import { useCounterStore } from './stores/counter'  
// 但在这里我们不会直接在 main.js 中使用它

2. 在组件外部使用 Store
示例:在路由守卫中使用 Store
假设你有一个名为 useUserStore 的 Store,用于管理用户状态,并且你想在路由守卫中检查用户是否已登录。

// router/index.js  
import { createRouter, createWebHistory } from 'vue-router'  
import { useUserStore } from './stores/user' // 假设你的 Store 在这里  
import pinia from '../main' // 引入 Pinia 实例(你可能需要根据你的项目结构来调整这个路径)  
  
const router = createRouter({  
  history: createWebHistory(process.env.BASE_URL),  
  routes: [  
    // ...你的路由配置  
  ],  
})  
  
// 在路由守卫中使用 Store  
router.beforeEach((to, from, next) => {  
  // 使用 pinia.useStore() 获取 Store 实例  
  const userStore = pinia.useUserStore()  
  
  // 假设有一个 isLoggedIn 的 getter 或 state 属性  
  if (to.meta.requiresAuth && !userStore.isLoggedIn) {  
    // 重定向到登录页面或执行其他操作  
    next('/login')  
  } else {  
    next()  
  }  
})  
  
export default router
本站无任何商业行为
个人在线分享 » Vue3 之 Pinia 核心概念(八)
E-->