1. 程式人生 > >Vue進階之元件(二)

Vue進階之元件(二)

什麼是slot

官網API的說法是:

在使用元件時,常常要像這樣組合它們:
<app>
<app-header></app-header>
<app-footer></app-footer>
</app>

注意兩點:

元件不知道它的掛載點會有什麼內容。掛載點的內容是由的父元件決定的。

元件很可能有它自己的模版。

為了讓元件可以組合,我們需要一種方式來混合父元件的內容與子元件自己的模板。這個過程被稱為 內容分發 (或 “transclusion” 如果你熟悉 Angular)。Vue.js 實現了一個內容分發 API ,參照了當前 Web元件規範草案,使用特殊的 元素作為原始內容的插槽。

先上一個demo

<div id="app">
        <my-component>
            <h1>Hello Vue.js!</h1>
        </my-component>
        <my-component></my-component>
    </div>
    <template id="myComponent">
        <div class="content">
            <h2>
This is Component</h2> <slot>如果沒有分發內容,則顯示slot中的內容</slot> <p>Say Something....</p> </div> </template>
Vue.component('my-component', {
    template: '#myComponent'
})
new Vue({
    el: '#app'
})

這個模板中有兩個component

   <my-component
>
<h1>Hello Vue.js!</h1> </my-component> <my-component></my-component>

第一個中間寫了一行 h1
第二個中間沒有寫。
我們來看看執行結果:
這裡寫圖片描述
也就是說,如果中間不寫分發內容的話,就會顯示slot中的內容(第二個component)。

用官方點的話來說,slot就是一個插槽。感覺只要component中寫了東西,就不會顯示slot了
就是插在component中,但是顯示在什麼地方呢?

具名的slot

下面這行程式碼在template中聲明瞭具名的插槽。

<template id="dialog-template">
        <div class="dialogs">
            <div class="dialog" v-bind:class="{ 'dialog-active': show }">
                <div class="dialog-content">
                    <div class="close rotate">
                        <span class="iconfont icon-close" @click="close"></span>
                    </div>
                    <!-- 具名的插槽 -->
                    <slot name="header"></slot>
                    <slot name="body"></slot>
                    <slot name="footer"></slot>
                </div>
            </div>
            <div class="dialog-overlay"></div>
        </div>
    </template>

完整程式碼,以及js

    <div id="app">
        <modal-dialog v-bind:show.sync="show">
            <!-- 具名插槽的使用 header-->
            <header class="dialog-header" slot="header">
                <h1 class="dialog-title">提示資訊</h1>
            </header>
            <!-- 具名插槽的使用 body-->
            <div class="dialog-body" slot="body">
                <p>你想在對話方塊中放什麼內容都可以!</p>
                <p>你可以放一段文字,也可以放一些表單,或者是一些圖片。</p>
            </div>
            <!-- 具名插槽的使用 footer-->
            <footer class="dialog-footer" slot="footer">
                <button class="btn" @click="closeDialog">關閉</button>
            </footer>
        </modal-dialog>
        <button class="btn btn-open" @click="openDialog">開啟對話方塊</button>
    </div>
    <template id="dialog-template">
        <div class="dialogs">
            <div class="dialog" v-bind:class="{ 'dialog-active': show }">
                <div class="dialog-content">
                    <div class="close rotate">
                        <span class="iconfont icon-close" @click="close"></span>
                    </div>
                    <!-- 具名的插槽 -->
                    <slot name="header"></slot>
                    <slot name="body"></slot>
                    <slot name="footer"></slot>
                </div>
            </div>
            <div class="dialog-overlay"></div>
        </div>
    </template>
</body>
Vue.component('modal-dialog', {
    template: '#dialog-template',
    props: ['show'],
    methods: {
        close: function() {
            this.show = false
        }
    }
})

new Vue({
    el: '#app',
    data: {
        show: false
    },
    methods: {
        openDialog: function() {
            this.show = true
        },
        closeDialog: function() {
            this.show = false
        }
    }
})

首先說一下:

v-bind:show.sync="show"
<js>
openDialog: function() {
            this.show = true
        },
closeDialog: function() {
            this.show = false
        }

是為了繫結對話方塊的顯示與否,只是不知道為什麼要用v-bind:show.sync,非同步模式?

最後總結
感覺slot很適合用來作為頁面的佈局,導航頭、內容、尾部導航。