學完component
是怎麼傳遞之後,看似完美,如果某天PM丟出一個需求,初步了解狀況後,發現有很多地方都可以組成元件來重複使用,但其實沒有這麼簡單,看起來一樣的區塊,其實裏面有很多結構不一樣,這時就可以針對裡面的小區域去做修改。
Slot
Vue
官網翻譯Slot
為插槽,我聯想到線上遊戲的武器,也會有各種插槽,用這個方式去想會比較容易理解:
你的人物角色就像是外部元件,你的名刀不知火就是內元件,遊戲系統有卡片功能,卡片可以插在你的道具上面(內元件),卡片就是你想要的從外部放入的文字,但前提是道具要打洞
成插槽:
<div id="app">
<h3> {{ text }} </h3>
<out-text>
<p>打洞成功</p>
</out-text>
<out-text>
</out-text>
</div>
const app = Vue.createApp({
data() {
return {
text: "外層元件",
product: {
name: "名刀不知火",
price: 200000,
}
}
}
});
app.component("outText",{
template: `
<div class="box">
<h3> {{ text }} </h3>
<div class="header">header</div>
<div class="main">
<slot> 預設值!</slot>
</div>
<div class="footer">footer</div>
</div>
`,
data() {
return {
text: "內部元件",
num: 3,
};
}
});
app.mount("#app");
內層元件的模板某區塊如果要由外層元件定義時,子元件一定要加上slot
,外層元件的模板打洞成功
才能正常顯示。
如果外層元件的模板,沒有任何元素時,就會顯示<slot> 預設值!</slot>
,可以觀察兩個子元件畫面渲染的差異。
slot
具名插槽一把武器只有一個插槽那怎麼夠啊!那我要四個該怎麼做呢?
這種情況握緊拳頭是沒有用的,在建立四個插槽需要先瞭解slot
有個屬性:name
,可以使用它來為插槽命名,子元件模板則使用v-slot
讓外層傳遞到子元件:
<div id="app">
<h3> {{ product.name }} </h3>
<out-text>
<template v-slot:header>波利卡片</template>
<template v-slot:main>瘋兔卡片</template>
<template v-slot:default></template>
<template v-slot:footer>禿鷹卡片</template>
</out-text>
</div>
const app = Vue.createApp({
data() {
return {
text: "外層元件",
product: {
name: "名刀不知火",
price: 200000,
}
}
}
});
app.component("outText",{
template: `
<div class="box">
<div class="header">
<slot name="header"></slot>
</div>
<div class="main">
<slot name="main"></slot>
<div>
<slot>未插卡!</slot>
</div>
</div>
<div class="footer">
<slot name="footer"></slot>
</div>
</div>
`,
data() {
return {
text: "內部元件",
num: 3,
};
}
});
app.mount("#app");
v-slot:header
可以改為#header的寫法較為簡潔,v-slot:default
預設如果主元件沒有值,就會由<slot>未插卡!</slot>
來代替。
slot
作用域先來觀察這段程式碼,並猜想畫面會是什麼呢?
<div id="app">
<h3> {{ product.name }} </h3>
<out-text>
<p> {{ product.name }} </p>
</out-text>
</div>
const app = Vue.createApp({
data() {
return {
text: "外層元件",
product: {
name: "名刀不知火",
price: 200000,
}
}
}
});
app.component("outText",{
template: `
<div class="box">
</div>
`,
data() {
return {
text: "內部元件",
product: {
name: "+9 獵人之弓",
price: 100000,
}
};
}
});
app.mount("#app");
。
。
。
。
答案是只會顯示外層元件data
裡的product.name
,因為兩個元件雖然都有一樣product
,但各自元件有屬於自己的data
與作用域,兩個product
是不同的屬性。<out-text><p> {{ product.name }} </p></out-text>
會無法顯示,是因為Vue
在編譯時,會以元件模板定義內容為主,會忽略掉{{ product.name }}
,除非在子元件模板加上slot
。
官網補充:父級模板裡的所有內容都是在父級作用域中編譯的;子模板裡的所有內容都是在子作用域中編譯的。
template
記得打洞變成slot
。name
v-slot:插槽名稱
,可縮寫為#
插槽名稱。以上如有錯誤,歡迎指教,下一篇講解slot
的資料傳遞。