網(wǎng)站建設(shè)是哪個專業(yè)最新新聞熱點事件2022
vue 中的依賴注入,官網(wǎng)文檔已經(jīng)非常詳細,筆者在這里總結(jié)一份
目錄
1、背景介紹
2、代碼實現(xiàn)
2.1、依賴注入固定值
2.2、 依賴注入響應(yīng)式數(shù)據(jù)
3、注入別名
4、注入默認值
5、應(yīng)用層 Provide
6、使用 Symbol 作注入名
1、背景介紹
為什么會出現(xiàn)依賴注入呢?其實它是要解決 Prop 逐級透傳問題
Prop 逐級透傳問題,即通常情況下,當(dāng)我們需要從父組件向子組件傳遞數(shù)據(jù)時,會使用 props,如果只是父傳子,這樣層級不深的結(jié)構(gòu),是比較簡單的;如果是層級非常深,祖太爺、太爺、爺、父、子、孫、重孫組件......,這樣多層級嵌套的組件,形成了一顆巨大的組件樹,此時,如果重孫組件需要祖太爺組件中的部分數(shù)據(jù),在這種情況下,如果僅使用 props 則必須將其沿著組件鏈逐級傳遞下去,這會非常麻煩。而且中間的爺、父等組件可能根本不關(guān)心這些 props,為了使重孫組件能夠訪問到它們,仍然需要定義并向下傳遞。如果組件鏈路非常長,可能會影響到更多這條路上的組件。這一問題被稱為“prop 逐級透傳”
vue 中提供 provide 和 inject 可以幫助我們解決這一問題,一個父組件相對于其所有的后代組件,會作為依賴提供者。任何后代的組件樹,無論層級有多深,都可以注入由父組件提供給整條鏈路的依賴
下圖摘自vue官網(wǎng)
?
2、代碼實現(xiàn)
下面代碼實現(xiàn)依賴注入
新建vue項目,這里筆者定義3個組件。圖書館組件Library(爺),圖書組件Book(父)、標題組件Title(孫),實現(xiàn)圖書館組件Library(爺)提供數(shù)據(jù),標題組件Title(孫)注入使用
項目結(jié)構(gòu)
?
2.1、依賴注入固定值
圖書館組件Library(爺)提供?bookName
<template><div><h1>圖書館</h1><Book/></div>
</template>
<script>
import Book from './Book.vue'
export default {components: {Book},provide: {bookName: '三國演義'},
}
</script>
圖書組件Book(父)
<template><div><h2>書名</h2><Title /></div>
</template>
<script>
import Title from './Title.vue'
export default {components: {Title}
}
</script>
標題組件Title(孫),注入bookName?
<template><div><p>標題</p><p>{{bookName}}</p></div>
</template>
<script>
export default {inject: ['bookName'],
}
</script>
App.vue,引入圖書館組件Library
<template><Library />
</template><script>
import Library from './components/Library.vue'export default {name: 'App',components: {Library}
}
</script>
運行效果
2.2、 依賴注入響應(yīng)式數(shù)據(jù)
上例2.1依賴注入的 bookName 是個固定的值,本例將 bookName 改成響應(yīng)式數(shù)據(jù)
圖書組件Book(父)和標題組件Title(孫)不需要改,只改圖書館組件Library(爺)即可
圖書館組件Library(爺)
為保證注入方和供給方之間的響應(yīng)性鏈接,需要使用 computed() 函數(shù)提供一個計算屬性
<template><div><h1>圖書館</h1><button @click="changeBookName">修改書籍名稱</button><Book/></div>
</template>
<script>
import { computed } from 'vue'
import Book from './Book.vue'
export default {components: {Book},provide() {return {bookName: computed(()=>this.bookName)}},data() {return {bookName: '三國演義'}},methods: {changeBookName() {this.bookName = '西游記'}}}
</script>
圖書組件Book(父)
<template><div><h2>書名</h2><Title /></div>
</template>
<script>
import Title from './Title.vue'
export default {components: {Title}
}
</script>
標題組件Title(孫)
<template><div><p>標題</p><p>{{bookName}}</p></div>
</template>
<script>
export default {inject: ['bookName'],
}
</script>
運行效果
點擊按鈕,修改圖書名稱
3、注入別名
上面例子中標題組件Title(孫)中注入的 bookName,使用是也是bookName,即訪問的本地屬性名和注入名是相同的;如果我們想要用一個不同的本地屬性名注入該屬性,我們需要在 inject 選項的屬性上使用對象的形式
看下面代碼
注入bookName,本地屬性使用 name
<template><div><p>標題</p><p>{{name}}</p></div>
</template>
<script>
export default {inject: {name: {from: 'bookName'}}
}
</script>
4、注入默認值
如果注入的屬性沒有任何組件提供,則會拋出一個運行時警告,如果注入一個值時不要求必須有提供者,那么我們應(yīng)該聲明一個默認值,和 props 類似
將圖書館組件Library(爺)中的provide注釋掉
<template><div><h1>圖書館</h1><button @click="changeBookName">修改書籍名稱</button><Book/></div>
</template>
<script>
import { computed } from 'vue'
import Book from './Book.vue'
export default {components: {Book},// provide() {// return {// bookName: computed(()=>this.bookName)// }// },data() {return {bookName: '三國演義'}},methods: {changeBookName() {this.bookName = '西游記'}}}
</script>
圖書組件Book(父)不變
<template><div><h2>書名</h2><Title /></div>
</template>
<script>
import Title from './Title.vue'
export default {components: {Title}
}
</script>
標題組件Title(孫)中添加注入的默認值
<template><div><p>標題</p><p>{{name}}</p></div>
</template>
<script>
export default {inject: {name: {from: 'bookName',default: '紅樓夢'}}
}
</script>
運行效果
?
5、應(yīng)用層 Provide
除了在一個組件中提供依賴,我們還可以在整個應(yīng)用層面提供依賴
在 main.js 中提供依賴
import { createApp } from 'vue'
import App from './App.vue'const app = createApp(App)
app.provide('title', '古典名著')
app.config.unwrapInjectedRef = true
app.mount('#app')
在標題組件Title(孫)中注入title
<template><div><p>標題</p><p>{{ title }}</p><p>{{name}}</p></div>
</template>
<script>
export default {inject: {name: {from: 'bookName',default: '紅樓夢'},title: {}}
}
</script>
運行效果
6、使用 Symbol 作注入名
如果有非常多的依賴提供,建議最好使用 Symbol 來作為注入名以避免潛在的沖突
筆者在components目錄下定義keys.js文件
keys.js 文件內(nèi)容
export const bookName = Symbol()
在圖書館組件Library(爺)中引入keys.js
<template><div><h1>圖書館</h1><button @click="changeBookName">修改書籍名稱</button><Book/></div>
</template>
<script>
import { computed } from 'vue'
import Book from './Book.vue'
import { bookName } from './keys.js'
export default {components: {Book},provide() {return {[bookName]: computed(()=>this.bookName)}},data() {return {bookName: '三國演義'}},methods: {changeBookName() {this.bookName = '西游記'}}}
</script>
在標題組件Title(孫)中引入keys.js
<template><div><p>標題</p><p>{{ title }}</p><p>{{name}}</p></div>
</template>
<script>
import { bookName } from './keys.js'
export default {inject: {name: {from: bookName,default: '紅樓夢'},title: {}}
}
</script>
運行效果
?
至此完