中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue3狀態管理之Pinia怎么使用

發布時間:2022-04-22 15:13:05 來源:億速云 閱讀:349 作者:iii 欄目:開發技術

這篇文章主要介紹“Vue3狀態管理之Pinia怎么使用”,在日常操作中,相信很多人在Vue3狀態管理之Pinia怎么使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Vue3狀態管理之Pinia怎么使用”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

    Vue3 新的發展方向(來源于尤大知乎)

    Vue 3 將在 2022 年 2 月 7 日 成為新的默認版本

    基于 Vite 的極速構建工具鏈

    <script setup> 帶來的開發體驗更絲滑的組合式 API 語法

    Volar 提供的單文件組件 TypeScript IDE 支持

    vue-tsc 提供的針對單文件組件的命令行類型檢查和生成

    Pinia 提供的更簡潔的狀態管理

    新的開發者工具擴展,同時支持 Vue 2/Vue 3,并且提供一個插件系統來允許社區庫自行擴展開發者工具面板。

    一、Pinia 簡介與基礎

    1.1 Pinia 簡介

    • 官方地址:https://pinia.vuejs.org/

    • Pinia 是 Vuex4 的升級版,也就是 Vuex5

    • Pinia 極大的簡化了Vuex的使用,是 Vue3的新的狀態管理工具

    • Pinia 對 ts的支持更好,性能更優, 體積更小,無 mutations,可用于 Vue2 和 Vue3

    • Pinia支持Vue Devtools、 模塊熱更新和服務端渲染

    1.2 Pinia 基礎

    &emsp;&emsp;Vuex 與 Pinia 對比

    • Vuex 中核心部分: State、Getters、Mutations(同步) 和 Actions(異步)

    • Pinia 中核心部分: State、Getters 和 Actions(同步異步均支持)

    &emsp;&emsp;Pinia 各部分作用

    • State: 類似于組件中data,用于存儲全局狀態

    • Getters: 類似于組件中的computed,根據已有的State封裝派生數據,也具有緩存的特性

    • Actions: 類似于組件中的methods,用于封裝業務邏輯,同步異步均可以

    &emsp;&emsp;Pinia 官方示例JS版本

    import { defineStore } from 'pinia'
    
    export const todos = defineStore('todos', {
      state: () => ({
        /** @type {{ text: string, id: number, isFinished: boolean }[]} */
        todos: [],
        /** @type {'all' | 'finished' | 'unfinished'} */
        filter: 'all',
        // type will be automatically inferred to number
        nextId: 0,
      }),
      getters: {
        finishedTodos(state) {
          // autocompletion! ?
          return state.todos.filter((todo) => todo.isFinished)
        },
        unfinishedTodos(state) {
          return state.todos.filter((todo) => !todo.isFinished)
        },
        /**
         * @returns {{ text: string, id: number, isFinished: boolean }[]}
         */
        filteredTodos(state) {
          if (this.filter === 'finished') {
            // call other getters with autocompletion ?
            return this.finishedTodos
          } else if (this.filter === 'unfinished') {
            return this.unfinishedTodos
          }
          return this.todos
        },
      },
      actions: {
        // any amount of arguments, return a promise or not
        addTodo(text) {
          // you can directly mutate the stat 00e
          this.todos.push({ text, id: this.nextId++, isFinished: false })
        },
      },
    })

    二、Pinia 在Vue3-Vite中的使用

    2.1 基礎使用流程

    ① 創建一個vue vite項目

    PS C:\Users\FORGET\Desktop\vue-pinia-demo> npm init vite@latest
    Need to install the following packages:
      create-vite@latest
    Ok to proceed? (y) y
    √ Project name: ... pinia-demo
    √ Select a framework: ? vue
    √ Select a variant: ? vue-ts
    
    Scaffolding project in C:\Users\FORGET\Desktop\vue-pinia-demo\pinia-demo...
    
    Done. Now run:
    
      cd pinia-demo
      npm install
      npm run dev
    PS C:\Users\FORGET\Desktop\vue-pinia-demo> cd .\pinia-demo\
    PS C:\Users\FORGET\Desktop\vue-pinia-demo\pinia-demo> npm install

    ② 安裝 pinia,-S是為了將其保存至package.json中,便于Git管理給其他人的使用

    PS C:\Users\FORGET\Desktop\vue-pinia-demo\pinia-demo> npm install pinia -S

    # package.json文件中
     "dependencies": {
        "pinia": "^2.0.9",
        "vue": "^3.2.25"
      },

    ③ 創建 pinia 實例并掛載到 vue中

    // main.ts 文件
    import { createApp } from 'vue'
    import App from './App.vue'
    import {createPinia} from 'pinia'
    // 創建 Pinia 實例
    const pinia = createPinia()
    // 創建 Vue 實例
    const app = createApp(App)
    // 掛載到 Vue 根實例
    app.use(pinia)
    app.mount('#app')

    ④ 在src文件下創建一個store文件夾,并添加index.ts

    // store/index.ts
    import { defineStore } from 'pinia'
    // 1. 定義容器、導出容器
    // 參數1:容器的ID,必須是唯一的,后面Pinia會把所有的容器掛載到根容器
    // 參數2:一些選項對象,也就是state、getter和action
    // 返回值:一個函數,調用即可得到容器實例
    
    export const useMainStore =  defineStore('main',{
        // 類似于Vue2組件中的data,用于存儲全局狀態數據,但有兩個要求
        // 1. 必須是函數,目的是為了在服務端渲染的時候避免交叉請求導致的數據狀態污染
        // 2. 必須是箭頭函數,這樣是為了更好的 TS 類型推導
        state:()=>{
            return {
                info:"pinia 可以使用"
            }
        },
        getters:{},
        actions:{}
    })
    
    // 2. 使用容器中的 state
    // 3. 通過 getter 修改 state 
    // 4. 使用容器中的 action 同步和異步請求

    ⑤ 在組件中使用

    <template>
      <h2>{{ mainStore.info}}</h2>
    </template>
    
    <script lang="ts" setup>
    import { useMainStore } from "../store";
    const mainStore = useMainStore();
    </script>
    
    <style>
    </style>

    2.2 state 中數據的解構訪問

    狀態管理中

    // store/index.ts
    state:()=>{
            return {
                info:"pinia 可以使用",
                count:10
            }
        },

    組件中

    <template>
      <h2>{{ mainStore.count }}</h2>
      <h2>{{ mainStore.info }}</h2>
      <hr />
      <h2>{{ count }}</h2>
      <h2>{{ info }}</h2>
      <p>
        <button @click="alertData">修改數據</button>
      </p>
    </template>
    
    <script lang="ts" setup>
    import { toRefs } from 'vue'
    import { storeToRefs } from 'pinia'
    import { useMainStore } from "../store";
    const mainStore = useMainStore();
    // 解構數據,但是得到的數據是不具有響應式的,只是一次性的
    // 相當于僅僅只是...mainStore而已,只是做了reactive處理,并沒有做toRefs
    // const { count, info } = useMainStore();
    // 解決方法:
    // 1. 通過使用toRefs函數,因為前面所說相當于是通過reactive處理,因此可以
    // const { count, info } = toRefs(mainStore);
    // 2. 通過pinia中提供的storeToRefs方法來解決,推薦使用
    const { count, info } = storeToRefs(mainStore);
    const alertData = () => {
      mainStore.count += 10
    }
    </script>
    
    <style>
    </style>

    2.3 state 中數據的修改方式(actions和組件中)

    一般的修改

    const alertData = () => {
      // 方式一:最簡單的方法,如下
      // 解構后更改方式
      // count.value += 10
      // 結構前更改方式
      // mainStore.count += 10
      // 方式二:若要同時修改多個數據,建議使用$patch來實現批量更新,在內部做了優化
      // mainStore.$patch({
      //   count: mainStore.count + 1,
      //   info: "hello"
      // })
      // 方式三:更好的批量更新方法,通過$patch傳遞一個函數來實現,這里的state就是useMainStore容器中的state
      mainStore.$patch(state => {
        state.count += 10
        state.info = "pinia批量更新"
      })
    }

    通過actions修改

    // store/index.ts
    // 類似于vue2組件的methods,用于封裝業務邏輯,修改state
    // // 注意:不能使用箭頭函數來定義actions,因為箭頭函數綁定外部的this
        actions:{
            changeState (){
                this.count += 10
                this.info = "actions修改數據"
            },
            changeStates (num:number){
                this.count += num + 2
                this.info = "actions修改數據"
            }
        }
    const alertData = () => {
      // 方式一:最簡單的方法,如下
      // 解構后更改方式
      // count.value += 10
      // 結構前更改方式
      // mainStore.count += 10
      // 方式二:若要同時修改多個數據,建議使用$patch來實現批量更新,在內部做了優化
      // mainStore.$patch({
      //   count: mainStore.count + 1,
      //   info: "hello"
      // })
      // 方式三:更好的批量更新方法,通過$patch傳遞一個函數來實現,這里的state就是useMainStore容器中的state
      // mainStore.$patch(state => {
      //   state.count += 10
      //   state.info = "pinia批量更新"
      // })
      // 方式四:通過 actions 來修改數據
      mainStore.changeState()
      mainStore.changeStates(10)
    }

    2.4 getters 的使用

    定義

    // 類似于組件的computed,用來封裝計算屬性,具有緩存的功能
        getters:{
        	 // 函數接收一個可選參數:state狀態對象
            count10(state){
                return state.count += 10
            },
            count10(state){
                return this.count += 10
            },
            // 若使用this.count,則必須指明返回數據的類型
            count11():number{
                return this.count += 11
            }
        },

    使用

    <h2>{{ mainStore.count10 }}</h2>

    三、Pinia 數據持久化

    保存至localStorage中

    import { defineStore } from 'pinia';
    const useLoginStore = defineStore({
      id: 'login',
      //   state: () => ({
      //     num: 1,
      //   }),
      state: () => ({
        info: 'pinia 可以使用',
      }),
      getters: {},
      actions: {
        alertInfo() {
          this.info = '可以可以,這個秒';
        },
      },
    });
    
    // 數據持久化
    // 1. 保存數據
    const instance = useLoginStore();
    instance.$subscribe((_, state) => {
      localStorage.setItem('login-store', JSON.stringify({ ...state }));
    });
    // 2. 獲取保存的數據,先判斷有無,無則用先前的
    const old = localStorage.getItem('login-store');
    if (old) {
      instance.$state = JSON.parse(old);
    }
    export default useLoginStore;

    使用 插件 pinia-plugin-persist 可以輔助實現數據持久化功能

    # 安裝插件
    pnpm install pinia-plugin-persist --save
    // main.ts文件中
    import { createPinia } from 'pinia';
    import { createApp } from 'vue';
    import App from './App.vue';
    import router from './router';
    import piniaPluginPersist from 'pinia-plugin-persist';
    const pinia = createPinia();
    pinia.use(piniaPluginPersist);
    const app = createApp(App);
    app.use(router);
    app.use(pinia);
    app.mount('#app');
    // 接著在對應的 store 里開啟 persist 即可。數據默認存在 sessionStorage 里,并且會以 store 的 id 作為 key。
    import { defineStore } from 'pinia';
    import piniaPluginPersist from 'pinia-plugin-persist';
    const useLoginStore = defineStore({
      id: 'login',
      //   state: () => ({
      //     num: 1,
      //   }),
      state: () => ({
        info: 'pinia 可以使用',
      }),
      // 開啟數據緩存
      persist: {
        enabled: true,
      },
      getters: {},
      actions: {
        alertInfo() {
          this.info = '可以可以,這個秒';
        },
      },
    });
    export default useLoginStore;

    其它設置,自定義保存名稱,保存位置和需要保存的數據

    // 開啟數據緩存
      persist: {
        enabled: true,
        strategies: [
          {
            // 自定義名稱
            key: 'login_store',
            // 保存位置,默認保存在sessionStorage
            storage: localStorage,
            // 指定要持久化的數據,默認所有 state 都會進行緩存,你可以通過 paths 指定要持久化的字段,其他的則不會進行持久化。
            paths: ['age'],
          },
        ],
      },

    到此,關于“Vue3狀態管理之Pinia怎么使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    朝阳市| 罗定市| 上高县| 绥江县| 灵山县| 宁明县| 安阳县| 泾阳县| 龙川县| 敦化市| 乐清市| 中西区| 疏附县| 上杭县| 开远市| 肇源县| 周宁县| 韩城市| 定边县| 屏边| 仪征市| 祁阳县| 泸定县| 昭通市| 昌宁县| 江安县| 岑溪市| 蒙城县| 大连市| 边坝县| 咸丰县| 朝阳县| 藁城市| 恩平市| 扬州市| 巴南区| 南汇区| 县级市| 嘉祥县| 墨竹工卡县| 余江县|