說說如何使用 Vue.js 中的 slot 實現內容分發

當需要組合組件,即混合父組件內容與子組件模板時,就需要用到 slot。

一個組件不管多么復雜,都是由以下三個部分組成的:

  1. props - 傳遞數據
  2. events - 觸發事件
  3. slot - 分發內容

1 組件作用域

html:

<div id="app">
    <child v-show="isShow"></child>
</div>

js:

Vue.component('child',{
    template:'<div>子組件內容</div>'
});

var app = new Vue({
    el: '#app',
    data: {
        isShow:true
    }
});

這里的 isShow 綁定的是父組件的數據。

html:

<div id="app2">
    <child2></child2>
</div>

js:

Vue.component('child2',{
    template:'<div v-show="isShow">子組件 2 內容</div>',
    data:function () {
        return {
            isShow:true
        }
    }
});

var app2 = new Vue({
    el: '#app2',
    data: {
    }
});

這里定義在子組件模板中的 isShow 綁定的是子組件的數據。

所以說,組件模板中的內容是在當前組件的作用域內被編譯的。

2 單個 slot

在子組件的模板定義中,加入 <slot> 元素就可以開啟一個 slot。如果父組件模板中,沒有在子組件標簽內定義任何內容,那么就會顯示之前在 <slot> 元素內定義的內容;如果子組件標簽內定義了內容,那么就會顯示這些內容。

html:


<div id="app3">
    <child3>
        <p>云計算推介會</p>
    </child3>
</div>

js:

Vue.component('child3', {
    template: '\
    <div>\
        <slot>\
            <p>天上不見鳥,風吹石頭跑,中國戈壁荒漠變身云基地</p>\
        </slot>\
    </div>\
    '
});

var app3 = new Vue({
    el: '#app3',
    data: {}
});

效果:

云計算推介會

如果 html 中的 child3 內未定義任何內容,那么就會顯示定義在 <slot> 元素中的內容 :

<div id="app3">
    <child3>
        
    </child3>
</div>

效果:

天上不見鳥,風吹石頭跑,中國戈壁荒漠變身云基地

注意: 子組件模板中的 <slot> 元素內定義的內容,它的作用域在子組件中。

3 命名 slot

我們可以給 slot 命名,來指定分發的內容。命名的 slot 可以與之前說的無命名的 slot 和諧共處。

html:

<div id="app4">
    <child4>
        <h2 slot="header">人工智能識別人體姿態的秘密</h2>
        <p>人體姿態識別成為人工智能最新滲透的領域。據國外媒體報道,英國曼徹斯特大學和西班牙馬德里大學的合作研究團隊最新AI步態識別技術識別準確率高達93%,是目前AI步態識別的最高水平。日本電信公司NTT
            East和科技公司Earth eye合作開發的AI
            Guardsman系統則可以通過肢體動作識別,實時追蹤顧客購物行為,幫助經營者及時發現商店中的小偷。瑞士洛桑聯邦理工學院生物機器人實驗室的步態識別系統可以精確計算走路時所消耗的卡路里,未來將搭載在一套可穿戴設備上,提醒用戶調整最佳走路姿勢,保護身體關節或更好地通過走路燃燒卡路里。</p>
        <div slot="footer">Copyright ? Deniro</div>
    </child4>
</div>

js:

Vue.component('child4', {
    template: '\
    <div class="page">\
        <div class="header">\
            <slot name="header"></slot>\
                <div class="main>">\
                <slot></slot>\
                </div>\
                <div class="footer">\
                    <slot name="footer"></slot>\
                </div>\
         </div>\
     </div>\
            '
});

var app4 = new Vue({
    el: '#app4',
    data: {}
});

渲染結果:

<div class="page">
  <div class="header">
    <h2>人工智能識別人體姿態的秘密</h2> 
    <div class="main>"> <p>人體姿態識別成為人工智能最新滲透的領域。據國外媒體報道,英國曼徹斯特大學和西班牙馬德里大學的合作研究團隊最新AI步態識別技術識別準確率高達93%,是目前AI步態識別的最高水平。日本電信公司NTT
            East和科技公司Earth eye合作開發的AI
            Guardsman系統則可以通過肢體動作識別,實時追蹤顧客購物行為,幫助經營者及時發現商店中的小偷。瑞士洛桑聯邦理工學院生物機器人實驗室的步態識別系統可以精確計算走路時所消耗的卡路里,未來將搭載在一套可穿戴設備上,提醒用戶調整最佳走路姿勢,保護身體關節或更好地通過走路燃燒卡路里。</p> </div>
     <div class="footer">
          <div>Copyright ? Deniro</div>
     </div>
  </div>
</div>

效果:

這個示例中的子組件,聲明了三個 <slot> 元素,只有 <div class="main>"> 內的 <slot> 元素沒有指定 name 屬性,所以也只有它會被填充子組件在 HTML 中定義的默認內容。

4 作用域 slot

作用域 slot 的使用場景是這樣的:既可以復用子組件的 slot,又可以擴展甚至改變 slot 中的內容。

html:

<div id="app5">
    <child5>
        <template scope="props">
            <p>父組件定義的內容</p>
            <p>{{props.content}}</p>
        </template>
    </child5>
</div>s

js:

Vue.component('child5', {
    template: '\
   <div class="child">\
    <slot content="子組件定義的內容"></slot>\
   </div>'
});
var app5 = new Vue({
    el: '#app5',
    data: {}
});

渲染結果:

<div id="app5">
  <div class="child">
    <p>父組件定義的內容</p> 
    <p>子組件定義的內容</p>
  </div>
</div>

我們在子組件模板的 slot 內定義了一個 content,然后在父組件的 template 中,通過 scope 屬性,將子組件中定義的 content 內容,傳遞過來。

5 訪問 slot

我們可以通過 $slot 來訪問被分發的內容。

html:

<div id="app6">
    <child6>
        <h2 slot="header">人工智能識別人體姿態的秘密</h2>
        <p>人體姿態識別成為人工智能最新滲透的領域。據國外媒體報道,英國曼徹斯特大學和西班牙馬德里大學的合作研究團隊最新AI步態識別技術識別準確率高達93%,是目前AI步態識別的最高水平。日本電信公司NTT
            East和科技公司Earth eye合作開發的AI
            Guardsman系統則可以通過肢體動作識別,實時追蹤顧客購物行為,幫助經營者及時發現商店中的小偷。瑞士洛桑聯邦理工學院生物機器人實驗室的步態識別系統可以精確計算走路時所消耗的卡路里,未來將搭載在一套可穿戴設備上,提醒用戶調整最佳走路姿勢,保護身體關節或更好地通過走路燃燒卡路里。</p>
        <div slot="footer">Copyright ? Deniro</div>
    </child6>
</div>

js:

Vue.component('child6', {
    template: '\
    <div class="page">\
        <div class="header">\
            <slot name="header"></slot>\
                <div class="main>">\
                <slot></slot>\
                </div>\
                <div class="footer">\
                    <slot name="footer"></slot>\
                </div>\
         </div>\
     </div>',
    mounted: function () {
        var header = this.$slots.header;
        console.log("header:" + header);
        console.log("headerInnerHTML:" + header[0].elm.innerHTML);

        var main=this.$slots.default;
        console.log("main:" + main);
        console.log("mainInnerHTML:" + main[1].elm.innerHTML);
    }
});
var app6 = new Vue({
    el: '#app6',
    data: {}
});

輸出結果:


一般在開發獨立組件的過程中,會用到 slot 訪問操作。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 組件(Component)是Vue.js最核心的功能,也是整個架構設計最精彩的地方,當然也是最難掌握的。...
    六個周閱讀 5,653評論 0 32
  • 什么是組件? 組件 (Component) 是 Vue.js 最強大的功能之一。組件可以擴展 HTML 元素,封裝...
    youins閱讀 9,528評論 0 13
  • 此文基于官方文檔,里面部分例子有改動,加上了一些自己的理解 什么是組件? 組件(Component)是 Vue.j...
    陸志均閱讀 3,866評論 5 14
  • 以下內容是我在學習和研究Vue時,對Vue的特性、重點和注意事項的提取、精練和總結,可以做為Vue特性的字典; 1...
    科研者閱讀 14,143評論 3 24
  • 于我,出游是看美景,也是品美食,會友人。 越年少,越愛景色。或許也是因為原本自己就有一顆懷舊的心吧,畢業幾年后的出...
    057Bonnie閱讀 199評論 5 2