為什麼使用slot
slot(插槽)
- 在生活中很多地方都有插槽,電腦usb的插槽,插板當中的電源插槽
- 插槽的目的是為了讓我們原來的裝置具備更多的擴充套件性
- 比如電腦的USB我們可以插入U盤,手機,滑鼠,鍵盤等等
元件中的插槽
- 元件的插槽也是為了讓我們的元件更具有擴充套件性
- 讓使用者決定元件內部的一些內容到底展示什麼
例子
- 移動開發中,幾乎每個頁面都有導航欄
- 導航欄我們必然封裝成一個外掛
- 一旦有了這個元件,我們就可以在多個頁面中複用了
如何封裝這類元件(slot)
- 最好的封裝方式就是將共性抽取到元件中,將不同的部分暴露為插槽
- 一旦我們預留了插槽,就可以讓使用者根據自己的需求,決定插槽中插入什麼內容
- 是搜尋框,是文字,是按鈕,由排程者自己決定
插槽的案例
<div id="app">
<cpn><button>按鈕</button></cpn>
<cpn><p>hello world</p></cpn>
<cpn><p>666</p></cpn>
</div>
<template id="cpn">
<div>
<h2>我是元件</h2>
// 插槽預留的位置,方便使用者自己填寫
<slot></slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
components: {
"cpn": {
template: `#cpn`,
}
}
})
</script>
上述程式碼幹了以下事情
1.定義了子元件cpn
,然後在子元件中預留了一個插槽,插槽的內容由使用者填寫
2.父元件中使用了3次子元件,3個子元件分別給插槽填寫了不同的內容
最後展示效果如下
插槽預設值
如果我們需要大量使用這個元件,而且元件預留的插槽,我們大多數都是填寫的返回按鈕,只有極少數填寫其他的,那麼這種情況就可以為插槽設定一個預設值
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<slot><button>返回</button></slot>
</div>
</template>
我們在子元件中設定了一個預設值為返回按鈕的插槽,那麼父元件在使用時如果不填寫任何內容,那麼預設就是返回按鈕
具名插槽
有時我們需要多個插槽。例如對於一個帶有如下模板的元件:
<template id="cpn">
<div>
<slot name="header"><span>頭部</span></slot>
<slot name="main"><span>中間</span></slot>
<slot name="footer"><span>頁尾</span></slot>
</div>
</template>
我們在元件中預留了3個插槽,但是這裡指定了3個名字,後續父元件使用v-slot
指定name
屬性後就能填寫自己的內容,比如如下程式碼
<div id="app">
<cpn>
<template v-slot:header>
<p>header頭部</p>
</template>
<template v-slot:footer>
<p>footer頁尾</p>
</template>
</cpn>
</div>
使用了cpn
元件,然後指定了插槽name
屬性為header
和footer
的內容,指定後自己填寫的內容就會替換預設的內容。
注意:這裡的語法格式是固定的,必須在使用template
標籤上繫結v-slot:插槽的名字
編譯作用域
通過外面傳給元件的變數,在以後使用插槽的時候是不能使用的
<div id="app">
<cpn v-show="isShow"></cpn>
</div>
<template id="cpn">
<p>hello</p>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
data: {
isShow: true
},
components: {
"cpn": {
template: `#cpn`,
data(){
return{
isShow: false
}
}
}
}
})
</script>
上面我們定義了子元件cpn
,子元件中有屬性isShow
,app例項中也定義了屬性isShow
,最後使用子元件cpn
時使用了v-show
,當值為true
顯示,值為false
不顯示
問題:v-show
中的isShow
的值是例項中的true
還是子元件中的false
答案:是true
,因為你使用的時候是在app
例項範圍內,所以isShow
會去從例項中的data
去查詢,雖然你是在cpn
子元件中繫結的,但是這裡的cpn
你只需要把他當做普通的標籤即可,如果你想讓isShow
的值為false
,那麼你只需要在子元件的template
模板中使用<p v-show="isShow">hello</p>
作用域插槽
預設在插槽中的程式碼只能使用全域性Vue
中的屬性,如果想要使用自定義元件中的屬性,那麼需要在定義slot
的時候使用v-bind
來進行繫結。
<div id="app">
<cpn>
<template v-slot:default="slot">
{{slot.data.firstName}}
</template>
</cpn>
</div>
<template id="cpn">
<div>
<slot :data="user">
{{user.lastname}}
</slot>
</div>
</template>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: "#app",
components: {
"cpn": {
template: `#cpn`,
data(){
return{
"user": {
"firstName": "甲",
"lastname": "殼蟲"
}
}
}
}
}
})
</script>
上述程式碼做了如下幾件事情
1.定義了子元件cpn
,在子元件中定義了user
2.在子元件cpn
的模板的插槽中繫結了屬性data
,且插槽的預設值為user.lastname
3.在html
中使用了子元件,並使用v-slot
繫結了插槽Prop
物件,這樣就可以通過物件名稱.子元件中繫結的屬性名稱(slot.data
),來訪問子元件中的資料