天天看點

Vue3項目實踐-第二篇(狀态管理-Pinia-01)

作者:繪芽研究社1号
Vue3項目實踐-第二篇(狀态管理-Pinia-01)

引用位址:

https://github.com/vuejs/pinia

https://pinia.web3doc.top/

目前内容

1 Pinia

1.1 概述

1.2 核心概念

2 快速建構

2.1 利用 vite 建構項目

2.2 安裝 Pinia

3 Store

3.1 什麼是Store?

3.2 如何定義Store?

3.3 如何使用 Store?

3.4 解析通路Pinia容器中的資料

Vue3項目實踐-第二篇(狀态管理-Pinia-01)

1.1 概述

Pinia 最初是在 2019 年 11 月左右重新設計使用 Composition API 。從那時起,最初的原則仍然相同,但 Pinia 對 Vue 2 和 Vue 3 都有效,并且不需要您使用組合 API。

Pinia 是 Vue 的存儲庫,它允許您跨元件/頁面共享狀态。如果您熟悉 Composition API,您可能會認為您已經可以通過一個簡單的 export const state = reactive({}). 這對于單頁應用程式來說是正确的,但如果它是伺服器端呈現的,會使您的應用程式暴露于安全漏洞。 但即使在小型單頁應用程式中,您也可以從使用 Pinia 中獲得很多好處:

  • dev-tools 支援 跟蹤動作、突變的時間線 Store 出現在使用它們的元件中 time travel 和 更容易的調試
  • 熱子產品更換 在不重新加載頁面的情況下修改您的 Store 在開發時保持任何現有狀态
  • 插件:使用插件擴充 Pinia 功能
  • 為 JS 使用者提供适當的 TypeScript 支援或 autocompletion 伺服器端渲染支援

1.2 核心概念

  • Store
  • State
  • Getters
  • Actions
  • Plugins

2 快速建構

2.1 利用 Vite 建構Vue3 的項目

  • 通過 指令npm init vite@latest 直接建構項目
  • 這裡我選擇的是 vue-ts
Vue3項目實踐-第二篇(狀态管理-Pinia-01)
  • 進入目錄,還原依賴 npm install 或 npm i
Vue3項目實踐-第二篇(狀态管理-Pinia-01)
  • 運作項目和預覽
Vue3項目實踐-第二篇(狀态管理-Pinia-01)
Vue3項目實踐-第二篇(狀态管理-Pinia-01)

2.2 安裝 Pinia

用 NPM 包管理器安裝 Pinia:

npm install pinia           

提示

如果您的應用使用 Vue 2,您還需要安裝組合 API:@vue/composition-api。 如果您使用 Nuxt,則應遵循這些說明。

Vue3項目實踐-第二篇(狀态管理-Pinia-01)

建立一個 pinia執行個體并将其挂載在Vue 根執行個體:

import { createApp } from 'vue'
import './style.css'
import App from './App.vue'

import { createPinia } from 'pinia'

// createApp(App).use(createPinia()).mount('#app')

// 建立 Pinia 執行個體
const pinia = createPinia();

const app = createApp(App)

// 把 Pinia 執行個體 挂載到 vue 根執行個體
app.use(pinia)

app.mount('#app')           

3 Store

3.1 什麼是 Store ?

一個 Store (如 Pinia)是一個實體,它持有未綁定到您的元件樹的狀态和業務邏輯。換句話說,它托管全局狀态。

它有點像一個始終存在并且每個人都可以讀取和寫入的元件。

它有三個概念,state、getters 和 actions 并且可以安全地假設這些概念等同于元件中的“資料”、“計算”和“方法”。

3.2 如何定義 Store?

正常情況下,在項目中建立 store 檔案夾,專門存放 相關代碼

Vue3項目實踐-第二篇(狀态管理-Pinia-01)

Store 是使用 defineStore() 定義的,并且它需要一個唯一名稱,作為第一個參數傳遞:

import { defineStore } from "pinia";

/**
 * 1. 定義容器
 * 建立檢索存儲執行個體的“useStore”函數
 *
 * @param id - 容器ID,必須是唯一
 * @param options - 容器選項
 */
export const useMainStore = defineStore("main", {
  // 類似于元件的 data ,用于存儲全局狀态
  state: () => {
    return { clickCount:100 };
  },
  // 類似于元件的Computed,用來封裝計算屬性,有緩存功能
  getters: {},
  // 類似于元件的 methods,封裝業務邏輯,修改state
  actions: {},
});           

3.3 如何使用 Store?

自定義一個元件,引用自定義 store

<template>
    <h2>使用 自定義 store :{{ storeModel.clickCount }}</h2>
</template>

<script lang="ts" setup>

import { useMainStore } from "../store/useMain";

const storeModel = useMainStore();

console.log(storeModel.clickCount);

</script>           

引用元件

<script setup lang="ts">
import StoreComponent from './components/StoreComponentDemo.vue';
</script>

<template>
  <StoreComponent />
</template>           

效果

Vue3項目實踐-第二篇(狀态管理-Pinia-01)

3.4 解析通路Pinia容器中的資料

修改 useMainStore

import { defineStore } from "pinia";

export const useMainStore = defineStore("main", {

  state: () => {
    return {
        clickCount:100,
        bookName :"《挖空地球》",
        bookAutor:"作者 張三"
    }
  }
});
           

修改元件

<template>
    <h2>使用 自定義 store </h2>
    <p>--------------------------------------</p>
    <p>
        <button @click="clickHandle">修改點選數</button>
    </p>
    <p>--------------------------------------</p>

    <p>書籍名稱:{{ storeModel.bookName }}</p>
    <p>書籍作者:{{ storeModel.bookAutor }}</p>
    <p>點選次數:{{ storeModel.clickCount }}</p>
    <hr>
    <p>書籍名稱:{{ bookName }}</p>
    <p>書籍作者:{{ bookAutor }}</p>
    <p>點選次數:{{ clickCount }}</p>
</template>

<script lang="ts" setup>

import { useMainStore } from "../store/useMain";

const storeModel = useMainStore();

console.log(storeModel.clickCount);

// 這種寫法有問題,因為這樣拿到的資料不是響應式的,是一次性的
const { clickCount, bookAutor, bookName } = storeModel

const clickHandle = ()=>{
    storeModel.clickCount++;
};
</script>           

效果:

Vue3項目實踐-第二篇(狀态管理-Pinia-01)

存在的問題:const { clickCount, bookAutor, bookName } = storeModel 不随着點選按鈕的點選,動态響應。

是以這種寫法:解析到的資料是一次性的,不是響應式的

針對上述問題(解決方式,利用 Pinia 元件 storeToRefs 方法,把解構出來的資料做 ref 做了響應代理):

  • 引用 pinia 元件 import { storeToRefs } from "pinia";
  • 改寫取值方法:const { clickCount, bookAutor, bookName } = storeToRefs(storeModel)
<template>
    <h2>使用 自定義 store </h2>
    <p>--------------------------------------</p>
    <p>
        <button @click="clickHandle">修改點選數</button>
    </p>
    <p>--------------------------------------</p>

    <p>書籍名稱:{{ storeModel.bookName }}</p>
    <p>書籍作者:{{ storeModel.bookAutor }}</p>
    <p>點選次數:{{ storeModel.clickCount }}</p>
    <hr>
    <p>書籍名稱:{{ bookName }}</p>
    <p>書籍作者:{{ bookAutor }}</p>
    <p>點選次數:{{ clickCount }}</p>
</template>

<script lang="ts" setup>
import { storeToRefs } from "pinia";
import { useMainStore } from "../store/useMain";

const storeModel = useMainStore();

console.log(storeModel.clickCount);

// 這種寫法有問題,因為這樣拿到的資料不是響應式的,是一次性的
// const { clickCount, bookAutor, bookName } = storeModel
// 解決上述問題
// import { storeToRefs } from 'pinia'
const { clickCount, bookAutor, bookName } = storeToRefs(storeModel)
const clickHandle = ()=>{
    storeModel.clickCount++;
};
</script>           
Vue3項目實踐-第二篇(狀态管理-Pinia-01)

持續更新ing

繼續閱讀