component
傳遞的最後一個招,前面示範了由內傳到外、外傳到內...等,但是子元件的子元件的子元件,需要父元件資料,我們只能使用props
,一個一個往下傳,這時就可以使用provide
和inject
的機制,直接傳遞到想要的子元件上,不管幾層都能達到,根本就是隔山打牛
provide
/inject
假設元件是以下的架構
#app
└─ listcomponent
├─ list-header
└─ list-main
└─ list-footer
在根元件(#app),把需要傳遞的的資料,定義在provide
:
const app = Vue.createApp({
data() {
return {
text: "隔山打牛"
};
},
provide() {
return {
provideText: this.text,
};
}
});
在要接收資料的子元件加上inject
:
components: {
"list-footer": {
inject: ["provideText"],
template: `
<div>list-footer: {{ provideText }} </div>`
}
}
完整範例:
<div id="app">
<h2>app</h2>
<list-header></list-header>
</div>
const app = Vue.createApp({
data() {
return {
text: "隔山打牛"
};
},
provide() {
return {
provideText: this.text,
provideText2: Vue.computed(() => this.text)
};
}
});
app.component("list-header", {
template: `
<div v-for="i in 3">
list-header:
<list-main></list-main>
</div>`,
components: {
"list-main": {
template: `
<div>
list-main:
<list-footer></list-footer>
</div>`,
components: {
"list-footer": {
inject: ["provideText","provideText2"],
template: `
<div>list-footer: {{ provideText }} </div>
<div>list-footer: {{ provideText2.value }}</div>
`
}
}
}
}
});
app.mount("#app");
透過provide
輸出的資料並不會隨著父層資料更新而改變,所以要透過Vue.computed()
進行包裝。
Vue.computed()
為了修正provid
輸出不會隨父層更新的問題,這邊使用文字輸入框來做示範:
<div id="app">
<h2>app</h2>
<input type="text" v-model="text">
<list-header></list-header>
</div>
v-model
綁定data
的text
,修改裡面的值,並觀察渲染文字的差異。
const app = Vue.createApp({
data() {
return {
text: "隔山打牛"
};
},
provide() {
return {
provideText: this.text,
provideText2: Vue.computed(() => this.text)
};
}
});
app.component("list-header", {
template: `
<div v-for="i in 3">
list-header:
<list-main></list-main>
</div>`,
components: {
"list-main": {
template: `
<div>
list-main:
<list-footer></list-footer>
</div>`,
components: {
"list-footer": {
inject: ["provideText","provideText2"],
template: `
<div>list-footer: {{ provideText }} </div>
<div>list-footer: {{ provideText2.value }}</div>
`
}
}
}
}
});
app.mount("#app");
provideText2
,使用Vue.computed
來包裝,子層inject
才會跟著連動。inject
接收的子元件,需要加上.value
才能正常顯示。因為使用包裝的computed
預設是getter()
參數,所以需要使用.value
回傳。