日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯網營銷解決方案
我把Vue3項目中的Vuex去除了,改用 Pinia

Pinia

公司主營業(yè)務:成都做網站、網站建設、移動網站開發(fā)等業(yè)務。幫助企業(yè)客戶真正實現互聯網宣傳,提高企業(yè)的競爭能力。創(chuàng)新互聯建站是一支青春激揚、勤奮敬業(yè)、活力青春激揚、勤奮敬業(yè)、活力澎湃、和諧高效的團隊。公司秉承以“開放、自由、嚴謹、自律”為核心的企業(yè)文化,感謝他們對我們的高要求,感謝他們從不同領域給我們帶來的挑戰(zhàn),讓我們激情的團隊有機會用頭腦與智慧不斷的給客戶帶來驚喜。創(chuàng)新互聯建站推出衛(wèi)濱免費做網站回饋大家。

pinia 的優(yōu)勢

相對于以前的 vuex,pinia具有以下優(yōu)勢

  • 更簡單的寫法,代碼更清晰簡潔,支持 composition api 和 options api 語法
  • 更完善的 typescript 支持,無需創(chuàng)建自定義復雜的包裝類型來支持 TypeScript,所有內容都是類型化的,并且 API 的設計方式盡可能利用 TS 類型推斷
  • 非常輕量,只有1kb的大小

不需要再注入魔法字符串等進行調用

安裝

yarn add pinia
// or
npm install pinia

定義、使用store

創(chuàng)建一個 pinia 并傳遞給 vue 應用

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

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

定義store

store的定義是通過 defineStore 這個函數,

它需要一個唯一的名稱,該名稱可以作為第一個參數傳遞,也可以用 id 熟悉傳遞。

import { defineStore } from 'pinia'
export const useMainStore = defineStore('main', {
// other options...
})

import { defineStore } from 'pinia'
export const useMainStore = defineStore({
id: 'main'
// other options...
})

該 id 是必要的,主要是用于 vue devtools

使用store

import { useMainStore } from '@/stores/main'

export default defineComponent({
setup() {
const store = useMainStore()
return {
store,
}
},
})

上述代碼中,useMainStore實例化后的,我們就可以在 store 上訪問 state、getters、actions 等(pinia中沒有mutations)。

該 store 是一個 reactive 對象,所以不需要 “.value”,也不能對其進行解構使用,否則失去響應性(類似 props)。

storeToRefs

如果一定要對其進行解構使用,可以使用 storeToRefs ,類似 vue3 中的 toRefs

import { storeToRefs } from 'pinia'

export default defineComponent({
setup() {
const store = useMainStore()
const { user, company } = storeToRefs(store)
return {
user,
company
}
},
})

state

定義state

在 pinia 中,定義 state 是在函數中返回 state 初始狀態(tài)

import { defineStore } from 'pinia'

const useMainStore = defineStore('main', {
state: () => ({
teacherName: '艾倫',
userList: [
{ name: '小明', age: 18 },
{ name: '小李', age: 15 },
{ name: '小白', age: 16 },
],
}),
})

export default useMainStore

訪問state

可以通過store 實例直接訪問

import useMainStore from '@/store/main'

export default defineComponent({
setup() {
const mainStore = useMainStore()
const teacherName = computed(() => mainStore.teacherName)
const userList = computed(() => mainStore.userList)

return {
teacherName,
userList,
}
},
})

也可以直接修改狀態(tài)

import useMainStore from '@/store/main'
export default defineComponent({
setup() {
const mainStore = useMainStore()
function change() {
mainStore.teacherName = '米利'
mainStore.userList.push({
name: '小琪',
age: 19
})
}
return {
change
}
},
})

雖然可以直接修改,但是出于代碼結構來說,全局的狀態(tài)管理還是不要直接在各個組件處隨意修改狀態(tài),應放于 action 中統(tǒng)一方法修改(沒有mutation了)

重置狀態(tài)

可以通過調用store 上的方法將狀態(tài)重置為初始狀態(tài)

const mainStore = useMainStore()
mainStore.$reset()

$patch

修改state還可以通過使用 $patch 方法

$patch 可以同時修改多個值,舉個例子

import useMainStore from '@/store/main'
export default defineComponent({
setup() {
const mainStore = useMainStore()
mainStore.$patch({
teacherName: '德普',
userList: [
{ name: '小明', age: 18 },
{ name: '小李', age: 15 },
]
})
return {}
},
})

但是,這種寫法的在修改數組時,例如我只想要把 userList 的中第一項"小明"的age 改為 20,也需要傳入整個包括所有成員的數組,這無疑增加了書寫成本和風險,于是一般都推薦使用以下的傳入一個函數的寫法

mainStore.$patch((state)=>{
state.teacherName = '德普'
state.userList[0].age = 20
})

監(jiān)聽訂閱state

通過 store.$subscribe() 的方法,

該方法的第一個參數接受一個回調函數,該函數可以在 state 變化時觸發(fā)

const subscribe = mainStore.$subscribe((mutation, state) => {
console.log(mutation)
console.log(state)
})

如上所示,該回調函數的兩個參數

其中 state 是 mainStore 實例,而 mutation 打印如下

可以發(fā)現,打印結果的mutation對象主要包含三個屬性

  • events :是這次state改變的具體數據,包括改變前的值和改變后的值等等數據
  • storeId :是當前store的id
  • type:type表示這次變化是通過什么產生的,主要有三個分別是“direct” :通過 action 變化的”patch object“ :通過 $patch 傳遞對象的方式改變的“patch function” :通過 $patch 傳遞函數的方式改變的

停止監(jiān)聽

上面代碼中,調用mainStore.$subscribe返回的值(即上方示例的 subscribe 變量)可以停止訂閱

subscribe()

store.$subscribe() 的方法的第二個參數options對象,是各種配置參數,包括

  • detached屬性,其值是一個布爾值,默認是 false, 正常情況下,當 訂閱所在的組件被卸載時,訂閱將被停止刪除,如果設置detached值為 true 時,即使所在組件被卸載,訂閱依然可以生效。
  • 其他屬性主要還有 immediate、deep、flush 等等,和 vue3 watch的對應參數效果一樣。

getter

定義getter

getter 是 store 中的 state 計算值,以defineStore中的getters屬性定義

getters屬性的值是一個函數,該函數的第一個參數是 state

const useMainStore = defineStore('main', {
state: () => ({
user: {
name: '小明',
age: 7,
},
}),

getters: {
userInfo: (state) => `${state.user.name}今年${state.user.age}歲了`,
// 這里想要正確推斷參數 state 的類型,則定義 state 時需要使用箭頭函數定義
},
})

上面代碼中,getters的值是箭頭函數,當getters的值是普通函數時,可以通過 this 訪問整個store實例(如下)

但是如果是普通函數,想要通過 this 獲取state的值并希望this的類型能正確推斷,同時希望函數的返回值類型正確推斷,我們需要聲明函數的返回類型。

getters: {
userDesc: (state) => `${state.user.name}今年${state.user.age}歲了`,
userBesidesDesc(): string{ // 需注明類型
return `${this.user.age}歲的${this.user.name}` // 可以使用 this 獲取值
},
returnUserInfo() {
return this.userDesc // 也可以使用 this 獲取其他getters
},
},

訪問getter

import useMainStore from '@/store/main'
export default defineComponent({
setup() {
const mainStore = useMainStore()

const userDesc = computed(() => mainStore.userDesc)
const userBesidesDesc = computed(() => mainStore.userBesidesDesc)
const returnUserInfo = computed(() => mainStore.returnUserInfo)

return {
userDesc,
userBesidesDesc,
returnUserInfo,
}
},
})

action

定義action

action 是 store 中的 方法,支持同步或異步。

action 定義的函數可以是普通函數從而可以通過 this 訪問整個store實例,同時該函數可以傳入任意參數并返回任何數據

const useMainStore = defineStore('main', {
state: () => ({
count: 0,
}),
actions: {
add() {
this.count++
},
addCountNum(num: number) {
this.count += num
},
},
})

調用action

setup() {
const mainStore = useMainStore()
function mainAction() {
mainStore.addCount()
}
function addCountTwo() {
mainStore.addCountNum(2)
}
return {
mainAction,
addCountTwo
}
},

監(jiān)聽訂閱action

通過 store.$onAction(),可以監(jiān)聽action的動作及結果等

該函數可以接收一個回調函數作為參數,回調函數的參數中有五個屬性,具體如下

const unsubscribe = mainStore.$onAction(({
name, // action 函數的名稱
store, // store 實例,這里是 mainStore
args, // action 函數參數數組
after, // 鉤子函數,在action函數執(zhí)行完成返回或者resolves后執(zhí)行
onError, // 鉤子函數,在action函數報錯或者rejects后執(zhí)行
}) => {})

舉個例子,

首先,定義一個store

import { defineStore } from 'pinia'
const useMainStore = defineStore('main', {
state: () => ({
user: {
name: '小明',
age: 7,
},
}),
actions: {
subscribeAction(name: string, age: number, manualError?: boolean) {
return new Promise((resolve, reject) => {
console.log('subscribeAction函數執(zhí)行')
if (manualError) {
reject('手動報錯')
} else {
this.user.name = name
this.user.age = age
resolve(`${this.user.name}今年${this.user.age}歲了`)
}
})
},
},
})
export default useMainStore

然后在 setup 中使用

import useMainStore from '@/store/main'
import { ref, defineComponent, computed } from 'vue'
export default defineComponent({
setup() {
const mainStore = useMainStore()

function subscribeNormal() {
mainStore.subscribeAction('小李', 18, false)
}

function subscribeError() {
mainStore.subscribeAction('小白', 17, true)
}

const unsubscribe = mainStore.$onAction(({
name, // action 函數的名稱
store, // store 實例,這里是 mainStore
args, // action 函數參數數組
after, // 鉤子函數,在action函數執(zhí)行完成返回或者resolves后執(zhí)行
onError, // 鉤子函數,在action函數報錯或者rejects后執(zhí)行
}) => {
console.log('action的函數名', name)
console.log('參數數組', args)
console.log('store實例', store)

after((result) => {
console.log('$onAction after函數', result)
})

onError(error => {
console.log('錯誤捕獲', error)
})
})

return {
subscribeNormal,
subscribeError,
}
},
})

如上,在 setup 中,調用了 subscribeNormal 函數后,頁面打印如下

調用了 subscribeError 函數后,頁面打印如下

同樣,可以通過調用 mainStore.$onAction 返回的值來手動停止訂閱,在上面代碼的例子中,即是

unsubscribe() // 手動停止訂閱

store.$onAction 默認在所在組件卸載時會被自動刪除,可以通過傳遞第二個參數 true,來將action訂閱和所在組件分開(即組件卸載時,訂閱依然有效)

mainStore.$onAction(callback, true)

store使用位置

在組件中使用時,useStore() 在大多數情況下都可以在調用后開箱即用。

在其他地方使用時,需確保在 pinia 激活使用后( app.use(createPinia()) )才能使用 useStore()

例如在路由守衛(wèi)中

import { createRouter } from 'vue-router'
import useMainStore from '@/store/main'
const router = createRouter({
// ...
})

// 報錯
const mainStore = useMainStore()

router.beforeEach((to) => {
// 正常使用
const mainStore = useMainStore()
})

在store中也可以訪問其他store

import { defineStore } from 'pinia'
import { useUserStore } from './user'

export const useMainStore = defineStore('main', {
getters: {
otherGetter(state) {
const userStore = useUserStore()
return userStore.data + state.data
},
},
actions: {
async fetchUserInfo() {
const userStore = useUserStore()
if (userStore.userInfo) {
...
}
},
},
})

pinia插件

pinia store 支持擴展,通過 pinia 插件我們可以實現以下

  • 給 store 添加新屬性
  • 給 store 添加新選項
  • 給 store 添加新方法
  • 包裝已存在的方法
  • 修改甚至刪除actions
  • ...

例如可以寫一個簡單的插件來給所有store添加一個靜態(tài)屬性

import { createPinia } from 'pinia'
const pinia = createPinia()
// 傳遞一個返回函數
pinia.use(() => ({ env: 'dev' }))
app.use(pinia)

然后,在所有其他的store都可以訪問到上面添加的 env 屬性

setup() {
const mainStore = useMainStore()
console.log(mainStore.env) // dev
}

插件函數

從上方代碼可以發(fā)現,pinia 插件是一個函數,這個函數有一個可選參數

import { PiniaPluginContext } from 'pinia'
function myPiniaPlugin(context: PiniaPluginContext) {
console.log(context)
}

context 打印出來主要有

  • app : 當前應用 Vue.createApp() 創(chuàng)建的 app
  • options : defineStore 配置的數據
  • pinia : 當前通過 createPinia() 創(chuàng)建的 pinia 實例
  • store :當前 store 實例

通過 context 我們可以在 store 上設置屬性

pinia.use(({ store }) => {
store.env = 'dev'
})

這樣,在所有其他的store都可以訪問到上面添加的 env 屬性

pinia 的 store 是通過 reactive 包裝的,可以自動解包它包含的任何 ref 對象

pinia.use(({ store }) => {
store.env = ref('dev')
})

通過上面插件,訪問store 的 env 時不需要 .value,就可以直接訪問

setup() {
const mainStore = useMainStore()
console.log(mainStore.env) // 不需要加 .value
}

添加外部屬性

當需要添加來自其他庫或不需要響應式的數據時,應該用 markRaw() 包裝傳遞的對象,例如

markRaw 來自 vue3,可以標記一個對象,使其永遠不會轉換為 proxy。返回對象本身。

import { markRaw } from 'vue'
import { router } from './router'
import { axios } from 'axios'

pinia.use(({ store }) => {
store.router = markRaw(router)
store.axios = markRaw(axios)
})

在插件內部使用$subscribe、$onAction

pinia.use(({ store }) => {
store.$subscribe(() => {
// react to store changes
})
store.$onAction(() => {
// react to store actions
})
})

新屬性的typescript支持

當通過插件添加新屬性時,可以擴展 PiniaCustomProperties接口

可以用設置get,set或者簡單聲明值的類型,以此來安全地寫入和讀取新加的屬性

import 'pinia'

declare module 'pinia' {
export interface PiniaCustomProperties {
set env(value: string | Ref)
get env(): string
// 或者
env: string
}
}

新聞名稱:我把Vue3項目中的Vuex去除了,改用 Pinia
網站網址:http://m.5511xx.com/article/djspedo.html