為何捐款
API 瀏覽器
升級指南 (Upgrade guide)
NEW!
quasar.config 檔案 (The quasar.config file)
將專案轉換為搭配 Vite 的 CLI (Convert project to CLI with Vite)
瀏覽器相容性 (Browser Compatibility)
支援 TypeScript (Supporting TypeScript)
目錄結構 (Directory Structure)
命令列表 (Commands List)
CSS 預處理器 (CSS Preprocessors)
路由 (Routing)
懶加載 - 代碼分割 (Lazy Loading - Code Splitting)
處理資源 (Handling Assets)
啟動檔案 (Boot Files)
預取功能 (Prefetch Feature)
API 代理 (API Proxying)
處理 Vite (Handling Vite)
處理 process.env (Handling process.env)
使用 Pinia 進行狀態管理 (State Management with Pinia)
使用 Vuex 進行狀態管理 (State Management with Vuex)
Linter
測試 & 審核 (Testing & Auditing)
開發行動應用程式
Ajax 請求
公開開發伺服器
搭配 Vite 的 Quasar CLI - @quasar/app-vite
使用 Pinia 的狀態管理

在大型應用程式中,由於多個狀態片段分散在許多組件及其互動之間,狀態管理通常變得複雜。人們常常忽略 Vue 實例中的真理來源是原始資料物件 - Vue 實例只是代理對它的存取。因此,如果您有一個應由多個實例共用的狀態片段,則應避免重複它並通過身份共用它。

如果您希望組件共用狀態,建議使用 Pinia。在深入研究之前,請先查看其文件。當與 Vue 開發者工具 瀏覽器擴充功能(如時間旅行偵錯)一起使用時,它有一個很棒的功能。

我們不會詳細介紹如何配置或使用 Pinia,因為它有很棒的文件。相反,我們將只向您展示在 Quasar 專案中使用它時資料夾結構的外觀。

index.js
# Pinia 初始化
<store>
# Pinia 商店...
<store>
# Pinia 商店...

當您搭建 Quasar 專案資料夾時,您可以選擇添加 Pinia。它將為您建立所有必要的配置。例如,建立處理您需要的所有 Pinia 相關程式碼的 /src/stores

如果您在專案建立期間未選擇 Pinia 選項,但稍後想添加它,那麼您需要做的就是查看下一節並建立 src/stores/index.[js|ts] 檔案(當您執行 quasar new store <name> 時,它會自動建立)

/src/stores/index.js

import { store } from 'quasar/wrappers'
import { createPinia } from 'pinia'

/*
 * If not building with SSR mode, you can
 * directly export the Store instantiation;
 *
 * The function below can be async too; either use
 * async/await or return a Promise which resolves
 * with the Store instance.
 */

export default store((/* { ssrContext } */) => {
  const pinia = createPinia()

  // You can add Pinia plugins here
  // pinia.use(SomePiniaPlugin)

  return pinia
})

添加 Pinia 商店

通過 $ quasar new 命令,使用 Quasar CLI 添加 Pinia 商店很容易。

$ quasar new store <store_name> [--format ts]

它將在 /src/stores 中建立一個資料夾,並以來自上述命令的 “store_name” 命名。它將包含您需要的所有樣板。

假設您要建立一個 “counter” Pinia 商店。您發出 $ quasar new store counter。然後您會注意到新建立的 /src/stores/counter.[js|ts] 檔案。

index.js
# Pinia 初始化
counter.js
# Pinia 商店

Pinia 商店範例

import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    counter: 0,
  }),
  getters: {
    doubleCount: (state) => state.counter * 2,
  },
  actions: {
    increment() {
      this.counter++;
    },
  },
})

我們已經建立了新的 Pinia 商店,但我們尚未在我們的應用程式中使用它。在 Vue 檔案中

<template>
  <div>
    <!-- Option 1 -->
    <div>Direct store</div>
    <!-- Read the state value directly -->
    <div>{{ store.counter }}</div>
    <!-- Use getter directly -->
    <div>{{ store.doubleCount }}</div>

    <!-- Manipulate state directly -->
    <q-btn @click="store.counter--">-</q-btn>
    <!-- Use an action -->
    <q-btn @click="store.increment()">+</q-btn>
  </div>

  <div>
    <!-- Option 2 -->
    <div>Indirect store</div>
    <!-- Use the computed state -->
    <div>{{ count }}</div>
    <!-- Use the computed getter -->
    <div>{{ doubleCountValue }}</div>

    <!-- Use the exposed function -->
    <q-btn @click="decrementCount()">-</q-btn>
    <!-- Use the exposed function -->
    <q-btn @click="incrementCount()">+</q-btn>
  </div>

  <div>
    <!-- Option 3 -->
    <div>Destructured store</div>
    <!-- Use the destructured state -->
    <div>{{ counter }}</div>
    <!-- Use the destructured getter -->
    <div>{{ doubleCount }}</div>

    <!-- Manipulate state directly-->
    <q-btn @click="counter--">-</q-btn>
    <!-- Use an action -->
    <q-btn @click="increment()">+</q-btn>
  </div>
</template>

<script>
import { computed } from 'vue';
import { useCounterStore } from 'stores/counter';
import { storeToRefs } from 'pinia';

export default {
  setup() {
    const store = useCounterStore();

    // Option 2: use computed and functions to use the store
    const count = computed(() => store.counter);
    const doubleCountValue = computed(() => store.doubleCount);
    const incrementCount = () => store.increment(); // use action
    const decrementCount = () => store.counter--; // manipulate directly

    // Option 3: use destructuring to use the store in the template
    const { counter, doubleCount } = storeToRefs(store); // state and getters need "storeToRefs"
    const { increment } = store; // actions can be destructured directly

    return {
      // Option 1: return the store directly and couple it in the template
      store,

      // Option 2: use the store in functions and compute the state to use in the template
      count,
      doubleCountValue,
      incrementCount,
      decrementCount,

      // Option 3: pass the destructed state, getters and actions to the template
      counter,
      increment,
      doubleCount,
    };
  },
};
</script>

有關定義 Pinia 商店的更多資訊.

在 Pinia 商店中存取路由器

只需在 Pinia 商店中使用 this.router 即可存取路由器。

這是一個範例

import { defineStore } from 'pinia'

export const useWhateverStore = defineStore('whatever', {
  // ...
  actions: {
    whateverAction () {
      this.router.push('...')
    }
  }
}