64. Vue中的插槽slot

需求

在Vue的組件開發中,有些情況組件中的 html 內容是需要通過父組件判斷之後,纔能有確認的。沒有理由對於父組件的判斷編寫多個存在一定重複代碼的組件來進行切換吧!這時候就需要使用到插槽 slot 了。

下面來寫一個代碼示例,講解一下這種情況以及插槽 slot 的基本使用。

父子組件傳遞dom元素使用問題的示例

首先編寫一個基礎的代碼,要求有一個子組件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue中插槽slot</title>
    <!--  1.導入vue.js  -->
    <script src="lib/vue.js"></script>
</head>
<body>

<!-- 2.創建app   -->
<div id="app">

    <child></child>

</div>

<!-- 3.創建vm   -->
<script>

    Vue.component("child", {
        template: "<div><h1>hello world</h1></div>"
    });

    let vm = new Vue({
        el: "#app",
        data: {},
    })
</script>

</body>
</html>

在上面的代碼中,我寫了一個簡單的全局組件 child,現在頁面上展示如下:

假設我需要通過父元素將一部分 html 內容傳遞到組件中使用,如果不使用 slot 的話,該怎麼操作呢?

使用父子組件props方式傳遞 html 內容

<child content="<h2>父組件傳遞的內容</h2>"></child>

Vue.component("child", {
    props: ['content'],
    template: "<div><h1>hello world</h1> {{content}} </div>"
});

此時,我們來看看頁面顯示 content 的內容,如下:

可以發現,我們的html內容並不能直接顯示,而只是顯示文本信息,沒有html標籤效果。那麼就需要 v-html 來設置處理了。

在子組件中使用 v-html 來顯示

Vue.component("child", {
props: ['content'],
template: `<div>
    <h1>hello world</h1>
    <div v-html="content"></div>
</div>`
});

頁面顯示效果如下:

這時候效果是出來了,但是可以看到這樣去寫其實非常麻煩。而且組件還要被一個 div 包裹才能顯示。那麼能不能用 template 標籤來包括,去掉 div 呢?

嘗試使用 template 標籤包括,去掉 div

此時頁面的顯示如下:

也就是說,按照這種方式,我們必須用 div 之類的 html 標籤來包裹,然後使用 v-html 才能正常顯示了。

但是這種寫法體驗肯定不好,此時就可以使用 插槽 slot 語法。

slot的基本使用

使用插槽 slot 傳遞父組件的 dom 元素

<child>
    <h2>父組件傳遞的內容</h2>
</child>

Vue.component("child", {
template: `<div>
    <h1>hello world</h1>
    <slot></slot>
</div>`
});

效果如下:

可以看到直接就顯示了html內容,並不需要 div 包裹、 props 參數傳遞等等。

定義插槽的默認內容

有些情況,可能父組件是不會去傳遞插槽的內容的,這時候我們就需要給插槽設置一個默認值,如下:

瀏覽器顯示如下:

命名 slot 的基本使用

上面我們解釋了slot 的基本使用,這裏還有更多的需求在裏面。如果,我寫一個後臺管理頁面的內容組件,一般都會分爲 header、center、footer 上中下三大區域內容。

其中 header 和 footer 是根據父組件變化的,也就是說可以將這兩個區域設置爲插槽 slot。下面來實現一下基礎效果。

使用多個slot 的基礎效果

頁面顯示如下:

現在是正常顯示默認值的,但是,我們怎麼針對特定的 slot 設置 dom 元素呢?

嘗試直接設置 slot 元素

頁面效果如下:

可以看到此時就會同時將所有的 dom 元素傳遞到 全部的 slot 中。當然,這並不是我們想要的效果。

使用命名插槽 slot 解決多個 slot 傳遞問題

<child>
    <h1 slot="header">header內容</h1>
    <h1 slot="footer">fooster內容</h1>
</child>

Vue.component("child", {
template: `<div>
    <slot name="header">header內容默認值</slot>

    <h1>center中間區域</h1>

    <slot name="footer">footer內容默認值</slot>
</div>`
});

頁面效果如下:

可以看到,通過命名 slot,可以將對應的內容放入對應的插槽中。

命名 slot 的更新寫法

上面的命名 slot 寫法是已經準備捨棄的寫法,雖然還可以使用。更新的寫法將採用:

在一個 template 元素上使用 v-slot 指令,並以 v-slot 的參數的形式提供其插槽slot 名稱name

<template v-slot:header>
    <h1>header內容</h1>
</template>

<slot name="header">header內容默認值</slot>

修改寫法之後的完整代碼如下:

<!DOCTYPE html>
<html lang="en" xmlns:v-slot="http://www.w3.org/1999/XSL/Transform">
<head>
    <meta charset="UTF-8">
    <title>Vue中插槽slot</title>
    <!--  1.導入vue.js  -->
    <script src="lib/vue.js"></script>
</head>
<body>

<!-- 2.創建app   -->
<div id="app">

    <child>
        <template v-slot:header>
            <h1>header內容</h1>
        </template>

        <template v-slot:footer>
            <h1>fooster內容</h1>
        </template>

    </child>

</div>

<!-- 3.創建vm   -->
<script>

    Vue.component("child", {
        template: `<div>
            <slot name="header">header內容默認值</slot>

            <h1>center中間區域</h1>

            <slot name="footer">footer內容默認值</slot>
    </div>`
    });

    let vm = new Vue({
        el: "#app",
        data: {},
    })
</script>

</body>
</html>

更多精彩原創Devops文章,快來關注我的公衆號:【Devops社羣】 吧:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章