1. 程式人生 > >vue2的元件之slot

vue2的元件之slot

介面寫多了,大家應該都會想到一個問題:JS的模組寫好以後可以在多個地方重複使用,HTML有沒有辦法做到呢?Vue給了我們這個能力,使用元件,就可以輕鬆做到。

最簡單的元件

初始化Vue例項之前,使用`Vue.component`方法註冊一個簡單的template,在HTML中,就可以直接使用。因為這裡會舉一連串的例子,就直接用`one`、`two`、`three`來作為元件名稱了。

<body>
    <div id="app">
        <one></one>
    </div>
</body>

Vue
.component('one', { template: '<li>這是一個item</li>' }) var app = new Vue({ el: '#app' })


元件名稱定義的時候有一點需要注意的,就是要使用中劃線分詞。比方說,我想新建一個叫list item的元件,元件的名稱就需要是`list-item`,在HTML中使用的時候也一樣:

<div id="app">
    <list-item></list-item>
</div>

Vue.component('list-item'
, { template: '<li>這是一個item</li>' })

元件的內容可以從資料獲取嗎?

可以。在元件的data方法裡面返回資料就可以了。跟Vue例項不一樣的是,元件的data對應一個function,在元件中想要用到的資料,需要從這個方法裡面返回(返回的資料型別是物件)。

<div id="app">
    <two></two>
</div>

Vue.component('two', {
    template: '<li>{{ listItem.name }}</li>'
, data: function () { return { // 在html中引入gamesDB.js listItem: window.games[0] } } })


元件的內容可以在HTML裡面定義嗎?

可以。在元件中使用`<slot>`吧。在HTML的元件中間定義的內容,就會被插入到`<slot>` tag的位置中去。除了直接定義文字之外,當然也可以寫HTML。

<div id="app">
    <three>item1</three>
    <three>item2</three>
    <three>item3</three>
</div>

Vue.component('three', {
    template: '<li><slot></slot></li>'
})


在沒有定義元件內容的時候,可以有預設的內容嗎?

可以。在`<slot>` tag中間設定的內容,就是預設的內容。

<div id="app">
    <four></four>
    <four>這是自定義的內容</four>
</div>

Vue.component('three', {
    template: '<li><slot>預設內容</slot></li>'
})


如果我想在不同的位置插入不同的內容呢?

使用具名`<slot>`吧。在template裡面設定好每個slot的名稱,在HTML中通過`slot`屬性指定內容要插入到哪個具名`<slot>`中。詳情請看下面的程式碼片段和註釋。

<div id="app">
    <five>
        <!-- 指定要插入header這個slot中 -->
        <ul slot="header" class="nav nav-tabs">
          <li class="active"><a href="#">Home</a></li>
          <li><a href="#">Profile</a></li>
          <li><a href="#">Messages</a></li>
        </ul>

        <!-- 指定要插入content這個slot中 -->
        <div slot="content">this is my awesome website</div>
    </five>
</div>

Vue.component('five', {
    template:
        '<div>' +
            '<div class="top-nav">' +
                // 設定slot的名稱為header
                '<slot name="header"></slot>' +
            '</div>' +
            '<div class="main">' +
                // 設定slot的名稱為content
                '<slot name="content"></slot>' +
            '</div>' +
        '</div>'
})


圖片中選中的這一行,因為在HTML中指定slot的時候使用了`div` tag所以文字被它包了起來,如果希望直接插入文字,可以使用`template`這個tag:

<div id="app">
    <five>
        <ul slot="header" class="nav nav-tabs">
            <!-- ... -->
        </ul>

        <!-- 改為使用template tag -->
        <template slot="content">this is my awesome website</template>
    </five>
</div>


既然元件相當於自定義了一個tag,那可以自定義tag的屬性嗎?

可以的。使用`component`的`props`來設定吧。這裡有一點千萬要記得,在`props`裡面,是駝峰式分詞,但是,在HTML裡面使用這個屬性的時候,需要用中劃線分詞,是中!劃!線!我最開始使用的時候,兩邊都習慣性地使用駝峰,結果死活沒有效果。最後才發現官方文件有說明……

<div id="app">
    <six user-name="john"></six>
</div>

Vue.component('six', {
    props: ['userName'],
    template: '<li>{{ userName }}</li>'
})


從屬性傳入的資料,元件內可以進行處理嗎?

可以。我們用計算屬性做例子吧。把屬性設定的文字轉換為全大寫。

<div id="app">
    <six user-name="john"></six>
</div>

Vue.component('six', {
    props: ['userName'],
    // 最後template中使用的是計算屬性
    template: '<li>{{ uppercaseName }}</li>',
    computed: {
        uppercaseName: function() {
            return this.userName.trim().toUpperCase()
        }
    }
})



這些自定義的屬性也可以用v-bind指令嗎?

YES!直接用官方的一個雙向資料繫結的例子吧:

<div id="app">
    <input type="text" v-model="inputMsg" />
    </br>
    <six :user-name="inputMsg"></six>
</div>

Vue.component('six', {
    props: ['userName'],
    template: '<li>{{ uppercaseName }}</li>',
    computed: {
        uppercaseName: function() {
            return this.userName.trim().toUpperCase()
        }
    }
})

var app = new Vue({
    el: '#app',
    data: {
        inputMsg: ''
    }
})



可以在元件裡面直接使用另外一個元件嗎?

當然可以。我們直接上例子吧:

<div id="app">
    <game-list></game-list>
</div>

Vue.component('game-list', {
    template:
        '<ul>' +
            // 直接使用第三個元件進行迴圈
            '<three v-for="game in games">{{ game.name }}</three>' +
        '</ul>',
    data: function () {
        return {
            games: window.games
        }
    }
})

這期的基本上把元件的基礎都過了一遍,視訊裡面會附加套用boostrap的css做一個自己的元件的內容。敬請期待下一期,元件通訊。


寫在最後