Vue組件化開發(fā)(三)——slot插槽的使用

前言

插槽是Vue框架中的一個重要的概念,插槽的存在使得我們的組件更加具有靈活性,同時在多個開源的組件庫中,我們也常??梢钥吹接行╅_源組件也同樣預(yù)留了插槽讓我們?nèi)ミM行自定義的開發(fā),可以說插槽算是Vue開發(fā)所必須掌握的知識點了。本篇文章將對Slot插槽的使用進行講解,同時對具名插槽和作用域插槽的使用場景進行介紹,希望對大家有所幫助。

一、為什么要使用Slot

相信有過項目開發(fā)經(jīng)驗的小伙伴一定知道,在項目中往往會有多個地方需要用到樣式相似,細節(jié)略有差異的組件,比如說導(dǎo)航欄和搜索欄,這些組件出現(xiàn)頻率比較高,但是在不同的場景下我們對于導(dǎo)航欄的內(nèi)容有著不同的需要。而如果為了這點細微的區(qū)別再專門寫一個組件會十分麻煩,而且復(fù)用性也很低。
可能有些讀者會覺得,這不難解決,對于子組件中不確定的地方我們可以交由父組件的props傳值來進行解決,比如導(dǎo)航欄中的標題,我們可以都交由父組件傳值來實現(xiàn)。(比如下面的導(dǎo)航欄1和導(dǎo)航欄2)
不錯,當(dāng)組件的變化程度不大時,這確實可以十分方便地解決組件復(fù)用的問題。但如果說我想要實現(xiàn)根據(jù)不同的場景,導(dǎo)航欄中部的位置可能是標題,也有可能是下拉框,是搜索框或者是其他自定義的組件呢?此時我們就很難單純通過props來拓展我們的組件靈活性了。(比如下面的導(dǎo)航欄1和導(dǎo)航欄3)

導(dǎo)航欄1

導(dǎo)航欄2

導(dǎo)航欄3

二、slot插槽的基本使用

在子組件中,使用特殊的元素<slot>就可以為子組件開啟一個插槽。該插槽插入什么內(nèi)容取決于父組件如何使用。我們可以看一下下面這個案例:
我們一共在Vue實例中使用了2次子組件,第一次父組件沒有往子組件中傳遞元素,第二次父組件有往子組件傳遞元素。

<body>
    <div id="app">
        <slot-component></slot-component>
        <slot-component>
            <div>
                <h4>父組件通過插槽改變默認子組件的默認內(nèi)容1</h4>
                <h4>父組件通過插槽改變默認子組件的默認內(nèi)容2</h4>
            </div>
        </slot-component>
    </div>
    <template id="myComponent">
        <div>
            <slot>我是插槽的默認內(nèi)容</slot>
        </div>
    </template>
    <script>
        Vue.component('slot-component',{
            template: '#myComponent'
        })
        let app = new Vue({
            el: '#app',
        })
    </script>
</body>
slot的基本使用

從結(jié)果上看,當(dāng)父組件沒有往子組件插槽中添加元素時,則會展示插槽中默認的內(nèi)容,而如果父組件有傳遞插槽內(nèi)容,則會覆蓋插槽的默認內(nèi)容,而后進行顯示。

三、具名插槽

在第二小節(jié)中,我們已經(jīng)知道了插槽的基本使用,但是當(dāng)子組件的功能比較復(fù)雜時,我們可能就要在組件中定義多個插槽,來滿足更加靈活的業(yè)務(wù)需要。比如上面舉例的京東導(dǎo)航欄,這個組件內(nèi)部可以拆分為三個插槽,分別對應(yīng)、、三個位置的內(nèi)容。
但想要在組件內(nèi)預(yù)留多個插槽有個前提條件,就是我們必須要讓每個插槽都有其對應(yīng)的唯一標識,這樣父組件傳遞內(nèi)容的時候,才能識別出來哪些內(nèi)容對應(yīng)哪個插槽。

我們可以看一下下面這個案例:
子組件內(nèi)定義了三個具名插槽,我們在父組件中進行子組件的調(diào)用,需要注意的是我們并沒有完全按照順序去傳遞對應(yīng)插槽的內(nèi)容。但實際上從演示結(jié)果中我們可以發(fā)現(xiàn),無論父組件傳遞的插槽內(nèi)容順序如何,最終解析的時候都會將傳入的插槽內(nèi)容根據(jù)slot name進行正確的渲染的。

<body>
    <div id="app">
        <slot-component></slot-component>
        <br/><br/><br/>
        <slot-component>
            <div class="common-slot slot2" slot="slot2">
                插槽2內(nèi)容
            </div>
            <div class="common-slot slot1" slot="slot1">
                插槽1內(nèi)容
            </div>
            <div class="common-slot slot3" slot="slot3">
                插槽3內(nèi)容
            </div>
        </slot-component>
    </div>
    <template id="myComponent">
        <div>
            <slot name="slot1">我是插槽1的默認內(nèi)容</slot>
            <slot name="slot2">我是插槽2的默認內(nèi)容</slot>
            <slot name="slot3">我是插槽3的默認內(nèi)容</slot>
        </div>
    </template>
    <script>
        Vue.component('slot-component',{
            template: '#myComponent'
        })
        let app = new Vue({
            el: '#app',
        })
    </script>
</body>
image.png

四、作用域插槽

(一)編譯作用域

在講解作用域插槽之前,我們需要先對編譯作用域進行理解。具體表現(xiàn)在父組件模板的所有東西都會在父級作用域內(nèi)編譯;子組件模板的所有東西都會在子級作用域內(nèi)編譯。
我們可以通過下面這個案例來理解這個規(guī)則:
父組件和子組件都使用了isShow來控制組件的顯示,同時在父子組件的data中,又都有同名的變量isShow。我們從結(jié)果中可以看到,定義在在父組件中子組件,其組件是否可見取決于父組件data中的變量值。而在子組件template中定義的isShow標識,則受子組件自身data變量的約束,也就是說此處子組件模板的變量取的是子級作用域中的變量值。

<body>
    <div id="app">
        <slot-component v-show="isShow"></slot-component>
    </div>
    <template id="myComponent">
        <div>
            <h2>HELLO</h2>
            <div v-show="isShow">
                HI
            </div>
        </div>
    </template>
    <script>
        Vue.component('slot-component', {
            template: '#myComponent',
            data() {
                return {
                    isShow: false
                }
            }
        })
        let app = new Vue({
            el: '#app',
            data: {
                isShow: true
            }
        })
    </script>
</body>
編譯作用域演示用例
(二)作用域插槽

在上一小節(jié)的演示中,我們已經(jīng)可以了解到編譯作用域的概念,也知道了父組件無法直接使用子組件內(nèi)部的數(shù)據(jù)(因為子組件模板內(nèi)部的數(shù)據(jù)是在子組件的作用域中的)。但有些場景下,我們又會需要父組件可以替換插槽的標簽,但是內(nèi)容由子組件來提供。那么,此時我們就可以使用作用域插槽來解決這個問題。

我們可以來看一下下面這個案例:子組件中存在一個數(shù)組,現(xiàn)在我們想要通過插槽的方式,來根據(jù)不同的需要實現(xiàn)數(shù)組的展示方式:
在父組件中,我們定義了2種展示數(shù)據(jù)的方式,一種為展示為列表形式,還有一種是每種語言以--進行分割。在使用上,子組件需要在插槽處通過:data的方式提供對外暴露的數(shù)據(jù),父組件在使用的時候,則是先在子組件內(nèi)部定義<template>標簽,從slot-scope屬性中取出slotProps參數(shù)(其實slotProps就是一個對象,里面封裝著所有子組件插槽對外暴露的數(shù)據(jù))。
我們通過slotProps.data就可以獲取到我們在子組件插槽中封裝的data數(shù)據(jù)啦

<body>
    <div id="app">
        <slot-component>
            <template slot-scope="slotProps">
                <ul>
                    <li v-for="lang in slotProps.data">{{lang}}</li>
                </ul>
            </template>
        </slot-component>
        <slot-component>
            <template slot-scope="slotProps">
                <ul>
                    <span v-for="(lang,index) in slotProps.data">
                        <span v-if="index<5">{{lang}}--</span>
                        <span v-else>{{lang}}</span>
                        </span>
                </ul>
            </template>
        </slot-component>
    </div>
    <template id="myComponent">
        <div>
            <slot :data="languages"></slot>
        </div>
    </template>
    <script>
        Vue.component('slot-component', {
            template: '#myComponent',
            data() {
                return {
                    languages: [
                        'python', 'java', 'go', 'c#', 'scala', 'javaScript'
                    ]
                }
            }
        })
        let app = new Vue({
            el: '#app',
        })
    </script>
</body>
作用域插槽演示用例

至此,有關(guān)插槽的內(nèi)容就到此結(jié)束啦,作用域插槽多見于常見的組件庫中(比較多是在table組件中出現(xiàn)),所以最好要熟悉插槽的原理和使用,這樣可以更好地簡化我們的開發(fā)工作

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容