官方 api有這樣一句話:這對選項須要一塊兒使用,以容許一個祖先組件向其全部子孫後代注入一個依賴,不論組件層次有多深,並在起上下游關係成立的時間裏始終生效。日常咱們的全局狀態管理統統都交給
Vuex
來,Vuex
也的確是很是好的工具,並被官方做爲指定的狀態管理器。今天給你們介紹有個新的思路進行狀態管理。可能你們對provide / inject
這對api
有點陌生,的確也是,日常開發中咱們基本也不會用到。vue
看圖片能夠知道,provide
指望傳入一個Object
,而inject
能夠接受的值包括(1)一個字符串數組 (2)一個對象。代碼以下:(最簡單的寫法)api
// 父組件 App.vue
export default {
name: 'App',
provide: {
parentKey: 'aaa'
}
}
複製代碼
// 子組件 chidlren.vue
export default {
inject: ['parentKey'],
created () {
console.log(this.parentKey)
}
}
複製代碼
在打印臺能夠看到aaa被輸出了出來,既然inject
指望值是個數組,那應該也能夠這樣數組
// 父組件 App.vue
export default {
name: 'App',
provide: {
parentKey: { a: 'haha' },
parentKey2: [1, 2]
}
}
複製代碼
// 子組件 chidlren.vue
export default {
inject: ['parentKey', 'parentKey2'],
created () {
console.log(this.parentKey, this.parentKey2)
}
}
複製代碼
以前咱們傳遞是個字符串,發現其實傳遞什麼均可以,對應的對象和數組都打印出來了。 若是僅僅只是這樣,好像也沒什麼。看到api有這樣一句話:bash
提示:
provide
和inject
綁定並非可響應的。這是刻意爲之的。然而,若是你傳入了一個可監聽的對象,那麼其對象的屬性仍是可響應的。app
咱們能夠試下:iview
// 父組件 App.vue
<template>
<div class="app">
<router-view></router-view>
<button @click="changeKey"> 按鈕</button>
</div>
</template>
export default {
provide () {
return {
parentKey: this.key
}
},
methods: {
changeKey () {
this.key.push(2)
}
},
data () {
return {
key: [1]
}
}
}
複製代碼
// 子組件 chidlren.vue
export default {
inject: ['parentKey'],
created () {
let afterKey = JSON.stringify(this.parentKey)
let timer = setInterval(() => {
console.log(this.parentKey)
if (afterKey !== JSON.stringify(this.parentKey)) clearInterval(timer)
}, 1000)
}
}
複製代碼
最後能夠看見當點擊按鈕以後,在子組件chidlren.vue
中輸出的值變化了,定時器也中止了。ide
這裏面有幾個要注意的地方 (1). 這時候provide
必須爲一個工廠函數,若是你是這樣寫的provide: {parentKey: this.key}
也就是跟以前這種寫法,控制檯會報未定義key的錯誤 (2)不要傳字符串之類的值過去,好比:parentKey: this.key
而你在data
中是這樣定義key
的key: 'aaa
,提示下,他並非一個可響應的數據,你可能會說,那不對啊,我在當前組件改變這個值,模板裏輸出的也會變啊。這時候其實可響應的值是this
當前組件 (3)你們不要試圖替換數組來響應(爲何說這條,由於不注意我也犯了這個錯誤 :) (4)一旦注入了某個數據,好比上面示例中的 parentKey
,那這個組件中就不能再聲明 parentKey
這個數據了,由於它已經被父級佔有)函數
注意:在變異 (不是替換) 對象或數組時,舊值將與新值相同,由於它們的引用指向同一個對象/數組。Vue 不會保留變異以前值的副本。(來源Vue官網)工具
好像說了這麼久,沒說到與標題相關的。:)-- 接下來久介紹下構建全局狀態管理的思路網站
// 父組件(也能夠說是根組件) App.vue
export default {
name: 'App',
provide () {
return {
app: this
}
},
methods: {
changeKey () {
this.key.push(2)
}
},
data () {
return {
key: [1],
transitionName: 'slide-right'
}
}
}
複製代碼
// 子組件 chidlren.vue
export default {
inject: ['app'],
created () {
console.log(this.app)
console.log(this.app.key)
this.app.changeKey()
}
}
複製代碼
這樣你就能夠拿到根節點app
全部的東西了,還能夠訪問他的方法。以此將根節點做爲狀態管理器。 若是你以爲這樣狀態多起來,十分難管理,你可使用混合mixins
,將不一樣的邏輯分開到不一樣的 js 文件裏。固然這種事是仁者見仁智者見智,你可使用this.$root
訪問根節點,還能夠掛載在Vue.prototype
的原型上。哈哈,這些方法是否是感受有點邪門歪道的感受。因此官網有這麼一句話:
provide 和 inject 主要爲高階插件/組件庫提供用例。並不推薦直接用於應用程序代碼中。
給你們介紹下這個網站dev.iviewui.com,這個網站就是使用此方法作出來的,這樣減小了Vuex
的依賴使用vue
自己做爲狀態管理器,固然,若是你的網站很大,仍是建議使用Vuex
。
這對api還有不少東西能夠挖掘的,好比使用ES2015的Symbol
做爲惟一值,inject
中可使用default
做爲默認值等等。用法仍是同窗們去看看官網。此次久到此爲止,清明放假了,仍是休息休息。:)
若有錯誤,歡迎指出。