1.前言
vue的父子元件通信用什麼?
:prop和$emit的組合。
如果是爺孫元件呢?
:那麼就要用父元件來轉發資料和事件了。
如果是太爺爺和孫子元件呢?
:當然是vuex啦
emmm 好的,沒我啥事了,我這就走。
不行,我還能再掙紮一會兒!肯定有一部分兄弟做的項目比較小,元件通信的情況不是很多,懶得引入vuex,那麼provide/inject就是爺孫(不限于爺孫/父子,中間隔了多少級都可以)通信問題的最好解決方案啦!
2.官方文檔抄過來的介紹
這對選項需要一起使用,以允許一個祖先元件向其所有子孫後代注入一個依賴,不論元件層次有多深,并在起上下遊關系成立的時間裡始終生效。
provide 選項應該是
一個對象或傳回一個對象的函數。該對象包含可注入其子孫的屬性。在該對象中你可以使用 ES2015 Symbols 作為 key,但是隻在原生支援 Symbol 和 Reflect.ownKeys 的環境下可工作。
inject 選項應該是:
一個字元串數組,或
一個對象(詳情點選 這裡 )
3.基本用法
// 祖先元件 提供foo
//第一種
export default {
name: "grandfather",
provide(){
return{
foo:'halo'
}
},
}
//第二種
export default {
name: "grandfather",
provide:{
foo:'halo~~~~'
},
}
//後代元件 注入foo
export default {
inject:['foo'],
}
上面的兩種用法有什麼差別嗎?
如果你隻是傳一個字元串,像上面的‘halo',那麼是沒有差別的,後代都能讀到。
如果你需要傳一個對象(如下所示代碼),那麼第二種是傳不了的,後代元件拿不到資料。是以建議隻寫第一種
//當你傳遞對象給後代時
provide(){
return{
test:this.msg
}
},
注意: 一旦注入了某個資料,比如上面示例中的 foo,那這個元件中就不能再聲明 foo 這個資料了,因為它已經被父級占有。
4.什麼時候才是可響應的?
如果你使用過vuex,那麼你會認為,上面的例子中,如果我把 foo:'halo' 改成 foo:'world' ,子元件會及時響應資料變更,視圖完成更新。
可惜,沒有
在vue官方文檔中有這麼一句話
提示: provide 和 inject 綁定并不是可響應的。這是刻意為之的。然而,如果你傳入了一個可監聽的對象,那麼其對象的屬性還是可響應的。
這裡不探讨vue為什麼要這麼設計,我這裡隻展示啥時候provide/inject可響應
provide(){
return{
test:this.msg
}
},
data() {
return {
msg: "Welcome to Your Vue.js App",
}
}
mounted(){
setTimeout(()=>{
this.msg = "halo world";
console.log(this._provided.msg)
//log:Welcome to Your Vue.js App
},3000)
},
如上所示,這樣做是不行的,列印出來的 provided 中的資料并沒有改,子元件取得值也沒變。
你甚至可以直接給 this._provided.msg 指派,但是 即使 是 _provided.msg 裡面的值改變了,子元件的取值,依然沒有變。
當你像下面這樣做的時候,就可以響應了
provide(){
return{
test:this.activeData
}
},
data() {
return {
activeData:{name:'halo'},
}
}
mounted(){
setTimeout(()=>{
this.activeData.name = 'world';
},3000)
}
這就是vue中寫道的 對象的屬性 是可以響應的
然而,如果你傳入了一個可監聽的對象,那麼其對象的屬性還是可響應的。
5.實作全局變量
全局變量?provide/inject不是隻能從祖先傳遞給後代嗎?沒錯,我們隻要綁定到最最頂層的元件即可。
就是你啦! app.vue
我們把一整個執行個體都扔給後代!
//app.vue
export default {
name: 'App',
provide(){
return{
app:this
}
},
data(){
return{
text:"it's hard to tell the night time from the day"
}
},
methods:{
say(){
console.log("Desperado, why don't you come to your senses?")
}
}
}
//其他所有子元件,需要全局變量的,隻需要按需注入app即可
export default {
inject:['foo','app'],
mounted(){
console.log(this.app.text);//擷取app中的變量
this.app.say();//可以執行app中的方法,變身為全局方法!
}
}
這個也是可響應的噢~
6.實作頁面重新整理
1 . 用vue-router重新路由到目前頁面,頁面是不進行重新整理的
2 . 采用window.reload(),或者router.go(0)重新整理時,整個浏覽器進行了重新加載,閃爍,體驗不好
那我們怎麼做呢?
跟上面的原理差不多,我們隻在控制路由的元件中寫一個函數(使用 v-if 控制 router-view 的顯示隐藏,這裡的原理不作贅述),然後把這個函數傳遞給後代,然後在後代元件中調用這個方法即可重新整理路由啦。
//app.vue
export default {
name: 'App',
provide(){
return{
reload:this.reload
}
},
data(){
return{
isShowRouter:true,
}
},
methods:{
reload(){
this.isShowRouter = false;
this.$nextTick(()=>{
this.isShowRouter = true;
})
}
}
}
//後代元件
export default {
inject:['reload'],
}
7.結尾
vue中有這樣的提示
注意: provide 和 inject 主要為高階插件/元件庫提供用例。并不推薦直接用于應用程式代碼中。
provide/inject平時用的比較少,多數用于開發元件,但某些情況下還是很好用的。
業務龐大而複雜的,還是建議使用 vuex ~
總結
以上所述是小編給大家介紹的vue中的provide / inject 有什麼用處,希望對大家有所幫助!