最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue3 狀態(tài)管理 Pinia 入門指南

 更新時(shí)間:2026年05月24日 09:37:55   作者:叫我少年  
Pinia 是 Vue 3 官方推薦的狀態(tài)管理庫(kù),相較于 Vuex 更加輕量、易于使用,下面就來(lái)詳細(xì)的介紹一下Vue3 狀態(tài)管理 Pinia 入門,感興趣的可以了解一下

很多剛接觸 Vue3 狀態(tài)管理的同學(xué)都會(huì)問(wèn):“Vuex 還沒(méi)學(xué)明白,怎么又出了個(gè) Pinia?”這篇就來(lái)聊聊 Pinia,看看它到底是什么、為什么要用它、以及怎么用好它。

  1. Pinia 是什么:Pinia 是 Vue 的全新?tīng)顟B(tài)管理庫(kù),它和 Vuex 有哪些核心區(qū)別?
  2. 如何定義 Store:掌握選項(xiàng)式和組合式兩種創(chuàng)建 Store 的風(fēng)格。
  3. 在組件中如何使用:學(xué)會(huì)在 setup 中正確地使用 Store 并保持響應(yīng)性。

一、使用場(chǎng)景

Pinia 適用于需要對(duì) Vue 應(yīng)用進(jìn)行全局狀態(tài)管理的場(chǎng)景:

  • 跨組件共享狀態(tài):例如用戶登錄信息、購(gòu)物車數(shù)據(jù)、主題配置等
  • 與后端 API 交互:集中管理 API 調(diào)用和數(shù)據(jù)緩存邏輯
  • 調(diào)試與開(kāi)發(fā)體驗(yàn):配合 Vue DevTools 進(jìn)行狀態(tài)追蹤和時(shí)間旅行
  • 類型安全:為 TypeScript 項(xiàng)目提供完整的類型推導(dǎo)支持
  • 模塊化管理:將不同領(lǐng)域的全局狀態(tài)拆分為獨(dú)立的 Store,易于維護(hù)和擴(kuò)展

二、注意事項(xiàng)

劃重點(diǎn): Pinia 在 Vue 2 和 Vue 3 中均可使用,但本文所有示例均基于 Vue 3 + Script Setup 語(yǔ)法。

  • ??defineStore?? 的 ID 必須唯一:每個(gè) Store 都需要一個(gè)唯一的 ID,用于 DevTools 的連接
  • 沒(méi)有 ?mutations??:與 Vuex 不同,Pinia 將狀態(tài)(state?)與變更邏輯(actions)直接統(tǒng)一,摒棄了繁瑣的 mutations
  • 避免過(guò)度使用全局狀態(tài):組件內(nèi)部能處理的數(shù)據(jù),不要提升到 Store 中

三、基本用法

3.1 安裝與配置

yarn add pinia
# 或
npm install pinia

main.ts 中創(chuàng)建 Pinia 實(shí)例并注冊(cè)到 Vue 應(yīng)用:

// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

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

app.use(pinia)
app.mount('#app')

3.2 定義 Store

Pinia 提供兩種風(fēng)格來(lái)定義 Store:選項(xiàng)式(Options API)組合式(Composition API) 。選擇哪個(gè)全憑個(gè)人喜好,但組合式風(fēng)格更適合復(fù)雜邏輯的復(fù)用。

選項(xiàng)式風(fēng)格:

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

export const useCounterStore = defineStore('counter', {
  // 狀態(tài)(數(shù)據(jù))
  state: () => ({
    count: 0,
    name: '我的計(jì)數(shù)器',
  }),
  // 計(jì)算屬性(派生數(shù)據(jù))
  getters: {
    // 使用箭頭函數(shù)時(shí),state 為第一個(gè)參數(shù)
    doubleCount: (state) => state.count * 2,
    // 需要訪問(wèn)其他 getter 時(shí),使用普通函數(shù)
    doubleCountPlusOne(): number {
      return this.doubleCount + 1
    },
  },
  // 操作方法(業(yè)務(wù)邏輯)
  actions: {
    increment() {
      this.count++
    },
    decrement() {
      this.count--
    },
    // 支持異步操作
    async incrementAsync() {
      await new Promise((resolve) => setTimeout(resolve, 1000))
      this.increment()
    },
    incrementBy(amount: number) {
      this.count += amount
    },
  },
})

組合式風(fēng)格(推薦):

// stores/user.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { api } from '@/services/api' // 假設(shè)的 API 服務(wù)

// 類型定義
interface User {
  id: number
  name: string
  email: string
}
interface LoginCredentials {
  username: string
  password: string
}

export const useUserStore = defineStore('user', () => {
  // 狀態(tài)(類似 options 的 data)
  const user = ref<User | null>(null)
  const isLoggedIn = ref(false)

  // 計(jì)算屬性(類似 options 的 getters)
  const userName = computed(() => user.value?.name || '游客')
  const userId = computed(() => user.value?.id || 0)

  // 操作方法(類似 options 的 actions)
  function login(credentials: LoginCredentials) {
    return api.login(credentials).then((response) => {
      user.value = response.user
      isLoggedIn.value = true
      return response
    })
  }

  function logout() {
    user.value = null
    isLoggedIn.value = false
  }

  async function fetchUserProfile() {
    if (!userId.value) return
    try {
      const profile = await api.getUserProfile(userId.value)
      user.value = { ...user.value, ...profile }
    } catch (error) {
      console.error('獲取用戶資料失敗:', error)
    }
  }

  // 返回需要暴露給外部的所有內(nèi)容
  return { user, isLoggedIn, userName, userId, login, logout, fetchUserProfile }
})

代碼解析:

  1. ??defineStore?:這是定義 Store 的核心函數(shù),第一個(gè)參數(shù)是 Store 的唯一 ID,第二個(gè)參數(shù)是 Store 的定義(可以是對(duì)象或函數(shù))。
  2. ??ref?? 和 ?computed??:在組合式風(fēng)格中,我們使用 Vue 的響應(yīng)式 API 來(lái)定義狀態(tài)和計(jì)算屬性,和寫(xiě)組件 script setup 一模一樣。
  3. ??return?? 語(yǔ)句:組合式 Store 必須 return 一個(gè)對(duì)象,對(duì)象中的屬性和方法才能被外部訪問(wèn)。

3.3 在組件中使用 Store

<template>
  <div>
    <h1>{{ counterStore.name }}</h1>
    <p>計(jì)數(shù): {{ counterStore.count }}</p>
    <p>雙倍計(jì)數(shù): {{ counterStore.doubleCount }}</p>
    <p>用戶名: {{ userStore.userName }}</p>

    <button @click="counterStore.increment()">增加</button>
    <button @click="counterStore.decrement()">減少</button>
    <button @click="counterStore.incrementBy(5)">增加5</button>
    <button @click="counterStore.incrementAsync()">異步增加</button>

    <button @click="login" v-if="!userStore.isLoggedIn">登錄</button>
    <button @click="userStore.logout()" v-else>退出</button>
  </div>
</template>

<script lang="ts" setup>
import { watch } from 'vue'
import { useCounterStore } from '@/stores/counter'
import { useUserStore } from '@/stores/user'
import { storeToRefs } from 'pinia'

const counterStore = useCounterStore()
const userStore = useUserStore()

// 關(guān)鍵:使用 storeToRefs 保持解構(gòu)后的響應(yīng)性
const { count, doubleCount } = storeToRefs(counterStore)
const { userName, isLoggedIn } = storeToRefs(userStore)

// 直接調(diào)用 action(action 本身就是方法,無(wú)需解構(gòu))
const login = () => {
  userStore
    .login({ username: 'admin', password: 'password' })
    .then(() => {
      console.log('登錄成功')
    })
    .catch((error) => {
      console.error('登錄失敗:', error)
    })
}

// 監(jiān)聽(tīng) Store 狀態(tài)變化
watch(
  () => counterStore.count,
  (newCount, oldCount) => {
    console.log(`計(jì)數(shù)從 ${oldCount} 變?yōu)?${newCount}`)
  }
)
</script>

代碼解析:

  1. ??storeToRefs??:這是 Pinia 提供的一個(gè)工具函數(shù),用于“解包” Store 的 state 和 getters。直接從 Store 解構(gòu) const { count } = counterStore? 會(huì)失去響應(yīng)性,而 storeToRefs? 保證了解構(gòu)后的每個(gè) ref 依然是響應(yīng)式的。
  2. 直接調(diào)用 ?actions??:actions? 是普通函數(shù),可以直接從 Store 對(duì)象上調(diào)用,不需要解構(gòu)。counterStore.increment()? 和 userStore.login() 都是正確的用法。
  3. ??watch?? 監(jiān)聽(tīng):你可以像監(jiān)聽(tīng)普通 ref? 一樣監(jiān)聽(tīng) Store 中的狀態(tài),使用 watch(() => counterStore.count, handler)。

剛接觸 Pinia,建議先從最典型的狀態(tài)(比如用戶登錄信息、全局配置)開(kāi)始使用,不要一開(kāi)始就把所有組件數(shù)據(jù)都放進(jìn) Store。寫(xiě)得順手了,再逐步將那些頻繁跨組件傳遞的 props 和 emit 改為 Store 管理,你會(huì)發(fā)現(xiàn)代碼瞬間清爽許多。

到此這篇關(guān)于Vue3 狀態(tài)管理 Pinia 入門指南的文章就介紹到這了,更多相關(guān)Vue3 狀態(tài)管理 Pinia內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!‍

相關(guān)文章

最新評(píng)論

宣武区| 北京市| 嫩江县| 工布江达县| 乌兰县| 饶阳县| 扶风县| 呼玛县| 滕州市| 紫云| 台前县| 河北区| 肃北| 色达县| 汤阴县| 呼伦贝尔市| 永和县| 敖汉旗| 太和县| 曲麻莱县| 鲁甸县| 桃园县| 盘山县| 云霄县| 南岸区| 九龙坡区| 县级市| 英山县| 府谷县| 阳西县| 余江县| 伊川县| 淮安市| 平潭县| 梅河口市| 同仁县| 九寨沟县| 新野县| 乡宁县| 嘉兴市| 临沧市|