vue2.x中的provide和inject用法小結(jié)
一、Vue中 常見的組件通信方式可分為三類
父子通信
父向子傳遞數(shù)據(jù)是通過 props,子向父是通過 events($emit); 通過父鏈 / 子鏈也可以通信($parent / $children); ref 也可以訪問組件實(shí)例; provide / inject; $attrs/$listeners;
兄弟通信
Bus Vuex
跨級(jí)通信
Bus; Vuex; provide / inject、 $attrs / $listeners、
二、provide、inject
1、類型
provide:Object | () => Object
inject: Array<string> | { [key: string]: string | Symbol | Object }2、詳細(xì)
provide 選項(xiàng)應(yīng)該是一個(gè)對(duì)象或返回一個(gè)對(duì)象的函數(shù)。該對(duì)象包含可注入其子孫的 property。
在該對(duì)象中可使用 ES2015 Symbols 作為 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的環(huán)境下可工作。
inject 選項(xiàng)應(yīng)該是:
一個(gè)字符串?dāng)?shù)組,或
一個(gè)對(duì)象,對(duì)象的 key 是本地的綁定名,value 是:
在可用的注入內(nèi)容中搜索用的 key (字符串或 Symbol),或
一個(gè)對(duì)象,該對(duì)象的:
from property 是在可用的注入內(nèi)容中搜索用的 key (字符串或 Symbol)
default property 是降級(jí)情況下使用的 value
provide 和 inject 主要在開發(fā)高階插件/組件庫(kù)時(shí)使用。并不推薦用于普通應(yīng)用程序代碼中。
這對(duì)選項(xiàng)是成對(duì)使用的。子孫組件想要獲取祖先組件得資源,那么怎么辦呢,總不能一直取父級(jí)往上吧,而且這樣代碼結(jié)構(gòu)容易混亂。這個(gè)就是這對(duì)選項(xiàng)要干的事情。3、示例
爺組件
<template>
<div>
<button @click="changeMsg">祖組件觸發(fā)</button>
<h1>祖組件</h1>
<parent></parent>
</div>
</template>
<script>
import parent from './parent.vue';
export default {
data(){
return{
obj:{
name:'JavaScript',
},
developer:'布蘭登·艾奇',
year:1995,
update:'2021年06月',
}
},
provide(){
return {
obj: this.obj, // 方式1.傳入一個(gè)可監(jiān)聽的對(duì)象
developerFn:() => this.developer, // 方式2.通過 computed 來計(jì)算注入的值
year: this.year, // 方式3.直接傳值
app: this, // 方式4. 提供祖先組件的實(shí)例 缺點(diǎn):實(shí)例上掛載很多沒有必要的東西 比如:props,methods。
}
},
components: {
parent,
},
methods:{
changeMsg(){
this.obj.name = 'Vue';
this.developer = '尤雨溪';
this.year = 2014;
this.update = '2021年6月7日';
},
},
}
</script>父組件
<template>
<div class="wrap">
<h4>子組件(只做中轉(zhuǎn))</h4>
<child></child>
</div>
</template>
<script>
import child from './child.vue';
export default {
components:{
child,
},
}
</script>孫組件
<template>
<div>
<h5>孫組件</h5>
<span>名稱:{{obj.name}}</span> |
<span>作者:{{developer}}</span> |
<span>誕生于:{{year}}</span> |
<span>最后更新于:{{this.app.update}}</span>
</div>
</template>
<script>
export default {
computed:{
developer(){
return this.developerFn()
}
},
inject:['obj','developerFn','year','app'],
}
</script>

對(duì)比一下前后差異:無論點(diǎn)擊多少次,孫組件中的誕生于 year 字段永遠(yuǎn)都是1995 并不會(huì)發(fā)生變化,通過 方式1、方式2、方式4傳值是可以響應(yīng)的。
正是官網(wǎng)所提到的:provide 和 inject 綁定并不是可響應(yīng)的。這是刻意為之的。然而,如果你傳入了一個(gè)可監(jiān)聽的對(duì)象,那么其對(duì)象的 property 還是可響應(yīng)的。
在孫組件中修改祖組件傳遞過來的值(方式1、方式4),發(fā)現(xiàn)對(duì)應(yīng)的祖組件中的值也發(fā)生了變化:
爺組件
<template>
<div>
<h1>祖組件</h1>
<span>名稱:{{obj.name}}</span> |
<span>最后更新于:{{update}}</span>
<parent></parent>
</div>
</template>
<script>
import parent from './parent.vue';
export default {
data(){
return{
obj:{
name:'JavaScript',
},
update:'2021年06月',
}
},
provide(){
return {
obj: this.obj,
app: this,
}
},
components: {
parent,
},
}
</script>父組件不變
孫組件
<template>
<div>
<button @click="changeMsg">孫組件觸發(fā)</button>
<h3>孫組件</h3>
<span>名稱:{{obj.name}}</span> |
<span>最后更新于:{{this.app.update}}</span>
</div>
</template>
<script>
export default {
inject:['obj','app'],
methods: {
changeMsg(){
this.obj.name = 'React';
this.app.update = '2020年10月';
}
},
}
</script>

4、響應(yīng)式
方法一:傳遞的參數(shù)用一個(gè)方法返回
// 父組件
data() {
return {
name: "卷兒"
}
},
provide: function() {
return {
newName: () => this.name
}
// 子組件
inject: ['newName'],
computed: {
hnewName() {
return this.newName()
}
}
<!-- 子組件中的使用方式 -->
<h2>{{ hnewName }}</h2> <!-- 推薦使用這種方法 -->
<h2>{{ newName() }}</h2>方法二:把需要傳遞的參數(shù)定義成一個(gè)對(duì)象
// 父組件
data() {
return {
obj: {
name: "卷兒"
}
}
},
provide: function() {
return {
// 傳遞一個(gè)對(duì)象
obj: this.obj
}
},
// 子組件
inject: ['obj'],
computed: {
// 也可以不用計(jì)算屬性重新定義
objName() {
return this.obj.name
}
}
<!-- 子組件中的使用方法 -->
<h2>obj的name: {{objName}}</h2>
<h2>obj的name: {{obj.name}}</h2>三、 總結(jié)
慎用 provide / inject
既然 provide/inject 如此好用,那么,為什么 Vue 官方還要推薦我們使用 Vuex,而不是用原生的 API 呢?
答: 前面提到過,Vuex 和 provide/inject 最大的區(qū)別:Vuex 中的全局狀態(tài)的每次修改是可以追蹤回溯的,而 provide/inject 中變量的修改是無法控制的。換句話說,不知道是哪個(gè)組件修改了這個(gè)全局狀態(tài)。
Vue 的設(shè)計(jì)理念借鑒了 React 中的單向數(shù)據(jù)流原則(雖然有 sync 這種破壞單向數(shù)據(jù)流的家伙),而 provide/inject 明顯破壞了單向數(shù)據(jù)流原則。試想,如果有多個(gè)后代組件同時(shí)依賴于一個(gè)祖先組件提供的狀態(tài),那么只要有一個(gè)組件修改了該狀態(tài),那么所有組件都會(huì)受到影響。這一方面增加了耦合度,另一方面,使得數(shù)據(jù)變化不可控。如果在多人協(xié)作開發(fā)中,這將成為一個(gè)噩夢(mèng)。
在這里,總結(jié)了使用 provide/inject 做全局狀態(tài)管理的原則:
- 多人協(xié)作時(shí),做好作用域隔離;
- 盡量使用一次性數(shù)據(jù)作為全局狀態(tài)
一層嵌套的父子組件可以使用props來傳值,props本身就是有相應(yīng)性的。
根據(jù)自身代碼選擇合適的傳值方式,并不一定非要用provide/inject的傳值。
到此這篇關(guān)于vue2.x中的provide和inject用法的文章就介紹到這了,更多相關(guān)vue2.x provide和inject用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue Router中獲取路由傳遞過來的參數(shù)(方法詳解)
在VueRouter中,可以通過動(dòng)態(tài)路由匹配和查詢參數(shù)`query`來傳遞參數(shù),并將路由參數(shù)或查詢參數(shù)作為組件的`props`傳遞,動(dòng)態(tài)路由匹配使用`route.params`訪問參數(shù),查詢參數(shù)使用`route.query`訪問,本文給大家介紹Vue Router中獲取路由傳遞過來的參數(shù),感興趣的朋友一起看看吧2025-02-02
vue移動(dòng)端模態(tài)框(可傳參)的實(shí)現(xiàn)
這篇文章主要介紹了vue移動(dòng)端模態(tài)框(可傳參)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
詳解vue通過NGINX部署在子目錄或者二級(jí)目錄實(shí)踐
這篇文章主要介紹了詳解vue通過NGINX部署在子目錄或者二級(jí)目錄實(shí)踐,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09
Vue 中使用lodash對(duì)事件進(jìn)行防抖和節(jié)流操作
這篇文章主要介紹了Vue 中使用lodash對(duì)事件進(jìn)行防抖和節(jié)流操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-07-07
Vue?cli3.0創(chuàng)建Vue項(xiàng)目的簡(jiǎn)單過程記錄
Vue CLI是一個(gè)基于Vue.js進(jìn)行快速開發(fā)的完整系統(tǒng),下面這篇文章主要給大家介紹了關(guān)于Vue?cli3.0創(chuàng)建Vue項(xiàng)目的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08

