在vue3使用Pinia

今年到今天已經過了一大半了,又有新的技術需要學習了。這次由於vue3的到來vuex也被官方deprecated , 隨之取代的則是Pina。

本篇紀錄學習Pina的相關筆記!

定義 一個 store

為什麼是一個呢?這是因為在pinia中可以將store模塊化, 所以可以有多個store,而每個store都是獨立的

安裝完pinia後新建一個stores的資料夾,然後在底下新增index.js

這裡要注意的是main作為第一個參數表達的是id的意思,只能是唯一,不可重複的

從下面的代碼中可以看到結構和vuex是相似的,最大的區別則是少了mutation.

// store/indxe.js
import { defineStore } from 'pinia'

// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main',{
  state:()=>{
    return {}
  },
  getters:{},
  actions:{}
})

在vue3中使用store

這裡看的是當你想要使用哪一個store則引用哪一個store

import { useStore } from '@/stores/counter'

export default {
  setup() {
    const store = useStore()

    return {
      // 可返回整個實例,並在模板中使用它
      store,
    }
  },
}

注意事項

這裡請注意,因為store是用reactive包裹成的對象,當使用解構時其資料將會失去響應式的作用
 

export default defineComponent({
  setup() {
    const store = useStore()
    // ❌ 這不起作用,因為它會破壞響應式
    // 這和從 props 解構是一樣的
    const { name, doubleCount } = store

    name // "eduardo"
    doubleCount // 2

    return {
      // 一直會是 "eduardo"
      name,
      // 一直會是 2
      doubleCount,
      // 這將是響應式的
      doubleValue: computed(() => store.doubleCount),
      }
  },
})

如果一定要使用解構,且只是讀取而不進行操作的時候可以使用pinia內建的storeToRefs來對任何响应式属性创建 refs

import { storeToRefs } from 'pinia'

export default defineComponent({
  setup() {
    const store = useStore()
    // `name` 和 `doubleCount` 是響應式引用
    // 這也會為插件添加的屬性創建引用
    // 但跳過任何 action 或 非響應式(不是 ref/reactive)的屬性
    const { name, doubleCount } = storeToRefs(store)

    return {
      name,
      doubleCount
    }
  },
})

改變數據

接下來可以讀取以後,要做的就是最數據進行修改,與vuex的不同是,vuex修改state時必須透過mutation來進行修改, 而pinia則是可直接對state進行修改, 方便且直觀許多

// store/indxe.js
import { defineStore } from 'pinia'

// useStore 可以是 useUser、useCart 之类的任何东西
// 第一个参数是应用程序中 store 的唯一 id
export const useStore = defineStore('main',{
  state:()=>{
    return {
       counter: 0
    }
  },
  getters:{},
  actions:{}
})


// test.vue
import { useStore } from '@/stores/counter'

export default defineComponent({
  setup() {
    const store = useStore()
    const store = useStore()
    const onBtnClick = () => {
       store.counter++
    }

    return {
      onBtnClick
  },
})

重置狀態: $reset

如果想要回到最初值(在這裡的範例是 0)的話則可使用$reset()

const store = useStore()

store.$reset()

改變狀態: $patch

如果要改變多個數值的時候則可以使用$patch, 那麼這裡跟剛剛提到的直接對state修改看起來結果是一致的,那麼為什麼要使用$patch呢?

$patch 是經過優化的,會加快修改速度,對程序的性能有很大的好處。所以如果是多條條數據同時更新狀態數據,推薦使用$patch方式更新。
const handleClickPatch = () => {
  store.$patch({
    count: store.count + 2,
    text: '我被修改了',
  });
};

不過官方提醒: 

這種語法應用某些突變非常困難或代價高昂:任何集合修改(例如,從數組中推送、刪除、拼接元素)都需要您創建一個新集合。

因此$patch 方法也接受一個函數來批量修改集合內部分對象的情況:

cartStore.$patch((state) => {
  state.items.push({ name: 'shoes', quantity: 1 })
  state.hasChanged = true
})

替換整個state

在pinia也允許替換整個state

store.$state = { counter: 666, name: 'Paimon' }

實施對state的監聽

<template>
  <div>
    {{ baseUrl }}
  </div>
  <div v-show="isShow">
    該我出現了
  </div>
  <button @click="changeData">
    通過actions改變數據
  </button>
</template>
 
<script>
import appStore from "@/store/app"
import {storeToRefs} from "pinia"
import {ref} from "vue"
 
export default {
  name: "PiniaSubscribe",
  setup() {
    const store = appStore()
    const {baseUrl} = storeToRefs(store)
    const afterChangeUrl = 'https://www.taobao.com/'
    let isShow = ref(false)
 
    const subscribe = store.$subscribe((mutation, state) => {
      /*
      * mutation主要包含三個屬性值:
      *   events:當前state改變的具體數據,包括改變前的值和改變後的值等等數據
      *   storeId:是當前store的id
      *   type:用於記錄這次數據變化是通過什麼途徑,主要有三個分別是
      *         “direct” :通過 action 變化的
                ”patch object“ :通過 $patch 傳遞對象的方式改變的
                “patch function” :通過 $patch 傳遞函數的方式改變的
      *
      * */
      // 我們就可以在此處監聽store中值的變化,當變化為某個值的時候,去做一些業務操作之類的
      console.log(mutation)
      console.log(state.baseUrl)
      if (state.baseUrl === afterChangeUrl) isShow.value = true
      else isShow.value = false
    }, {detached: false})  //第二個參數options對象,是各種配置參數
    //detached:布爾值,默認是 false,正常情況下,當訂閱所在的組件被卸載時,訂閱將被停止刪除,
    // 如果設置detached值為 true 時,即使所在組件被卸載,訂閱依然在生效
    //參數還有immediate,deep,flush等等參數 和vue3 watch的參數是一樣的,多的就不介紹了,用到再看文檔吧
 
    // 停止訂閱
    // subscribe()  //調用上方聲明的變量值,示例(subscribe),即可以停止訂閱
 
    function changeData() {
      store.changeState(afterChangeUrl)
    }
 
    return {
      isShow,
      baseUrl,
      changeData
    }
  }
}
</script>

以上不定時更新~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值