iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 23
0
自我挑戰組

前端新手筆記-Vue.js系列 第 23

Day23 Vue Component(元件)-slot元件插槽

本文同步發表於Andy's Blog

前言

在介紹slot之前,我們必須先瞭解一個觀念:編譯作用域
我們先來看個範例
codepen連結

<div id="app">
<div class="parent">{{msg}}</div>
<child>{{msg}}</child>
</div>

猜猜看,child元件中是否會印出父層的msg:I'mparent內容?
答案是不會的!原因是目前child所處的位置是父層作用域,當然不會印出子層內容~

補充:在Vue生命週期中,Vue會在created階段時判斷是否有template,如果有vue則會去編譯template內容,也因此,child元件不會顯示I'mparent內容
https://ithelp.ithome.com.tw/upload/images/20191009/20114645YYilPuEj6G.png

圖示結果:
https://ithelp.ithome.com.tw/upload/images/20191009/20114645DNIetTy2Ci.png

小結論:

1.父層作用域在父層編譯
2.子層作用域在子層編譯
若要突破作用域編譯問題,就要使用到slot


Slot簡介

參考資料:Summer 夏天Vue.js: Slot
目的:突破作用域,將父層內容傳遞進來!通常會應用在如果內容不一定要放入component中時,可以透過slot傳遞一整個html結構進來。

Slot 是一種用於內容分配(Content Distribution / Transclusion)的元件,適用於複雜或巢狀元件的實作上,可以想像成是空間預留的方法,在迭代過程中再把內容塞進去。

卡斯伯老師在課堂上將slot分為三種:
1.沒有slot的狀態

  <no-slot-component>
    <p>這是一段沒有插槽使用的狀態</p>
  </no-slot-component>

說明:即使寫p段落文字在子元件中,在html上依舊不會顯示。因為元件中的內容都會被模板替換掉。這就是上方提到作用域編譯的問題~

2.單組slot
特點:在模板中添加<slot><slot/>
HTML部分

  <single-slot-component>
    <p>使用這段取代原本的 Slot。</p>
  </single-slot-component>

template部分

<script type="text/x-template" id="singleSlotComponent">
<div class="alert alert-warning">
  <h6>我是一個元件</h6>
  <slot>
    如果沒有內容,則會顯示此段落。
  </slot>
</div>
</script>

畫面上,就可以將<p>使用這段取代原本的 Slot。</p>呈現在畫面上!如下
https://ithelp.ithome.com.tw/upload/images/20191009/20114645IWKZBTkNyY.png

3.多組slot(具名插槽)
簡單來說,將內容放入指定位置
寫法:
1.在html加入slot
2.在元件模板插入 name
練習連結
HTML部分

<child>
      <p>123</p>
      <h1 class="header" slot="header">這是 HEADER</h1>

      <p>A paragraph for the main content.</p>
      <p>And another one.</p>

      <p class="footer" slot="footer">這是 FOOTER</p>

</child>

<template id="child-template">
    <div class="container">
      <header>
        <slot name="header">Default Header</slot>
      </header>
      <hr>

      <main>
        <slot>Default Body</slot>
      </main>

      <hr>
      <footer>
        <slot name="footer">Default Footer</slot>
      </footer>
    </div>
  </template>

補充:html結構中若不想顯示標籤如a、header,可以使用<template>,這樣就不會顯示標籤摟~

練習一下

猜猜看下面這個範例child元件,會印出什麼內容?
練習連結
HTML部分

<div id="app">
<div class="parent">{{ msg }}</div>
  <child>
    <div>This "msg" is from parent: {{ msg }}</div>
  </child>
</div>

<template id="child-template">
    <div class="child">
      <div>{{ msg }}</div>
      <!-- 預設slot文字 -->
      <slot> Default Slot Content </slot>
    </div>
</template>

JavaSvript部分

// children component
    Vue.component('child', {
      template: '#child-template',
      data: function () {
        return {
          msg: 'I\'m child.'
        };
      }
    });

    // parent component
    var parent = new Vue({
      el: '#app',
      data: {
        msg: 'I\'m parent.'
      }
    });

答案是:
https://ithelp.ithome.com.tw/upload/images/20191009/20114645wwTeKanLW0.png

原因:之所以child中的msg會印出I'm parent字樣,就是因為child所在區域,還是在父層。因此編譯作用域還是在父層內。

後記

在2.6.0中,我們為具名插槽和作用域插槽引入了一個新的統一的語法(即v-slot指令)。它取代了slot和slot-scope

參考資料


上一篇
Day22 Vue Component(元件) is動態切換元件
下一篇
Day24 Vue CLI2與Webpack介紹
系列文
前端新手筆記-Vue.js30

尚未有邦友留言

立即登入留言