iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 16
1
Modern Web

「小孩才做選擇,我全都要。」小白也能輕鬆瞭解的 Vue.js 與 D3.js 。系列 第 16

[ Vue.js ] 插槽 slot

學習完 Vue 之後,想要透過單元測試守護你的專案,但又不知道從何起手?
別擔心,快來訂閱作者最新系列文 《小白也能輕鬆瞭解的 Vue3 單元測試!》
讓你的 Vue 專案更上一層樓!


渲染範圍

使用樣本語法時,我們可以在 HTML 中使用兩對花括號來表示要顯示的資料,並且透過 Vue.js 實體中的 el 來指定 Vue.js 渲染的範圍,並且在子元件的 template 中同樣也可以使用,然而如果是在 HTML 中的子元件標籤裡直接使用則會導致失效,如下面範例:

HTML部分:

<div id="app">
    {{ message }}
    <child-element>{{ childMessage }}</child-element>
</div>

JavaScript部分:

Vue.component('child-element', {
  template:`<div></div>`,
  data(){
    return {
      childMessage : 'child component'
    }
  }
})


let vm = new Vue({
  el:'#app',
  data:{
    message : 'parent component'
  }
})

最後樣板語法將不會顯示任何資料。(這並非是什麼 BUG,而是 Vue.js 預設的渲染。)

slot

假使想要在子元件標籤中放些自定義的文字或內容,可以透過 <slot> 標籤來達成,我們試著將上面的元件稍微改寫一下:

JavaScript 部分:

Vue.component('child-element', {
  template:
  `
  <div>
    <slot></slot> // 加入 slot 標籤
  </div>
  `,
  data(){
    return {
      childMessage : 'child component'
    }
  }
})

HTML 部分:

<div id="app">
    {{ message }}
    <child-element>
        {{ message }} //這裡的message 將會傳入父元件的資料物件
    </child-element>
</div>

這樣將會使得在 <child-element></child-element> 標籤中的資料,傳入到子元件裡的<slot></slot>的位置,將其替換掉。並且我們可以也可以傳入 HTML 元素、甚至是其他的元件以及父元件的資料物件:

注意當使用這樣的方法在子元件內使用樣板語法傳入資料,此時傳入的資料將會是父元件的資料物件,若要使用子元件的資料物件,仍然只能在子元件的template中去呼叫。

而當我們使用 <slot> 後,若沒有 HTML 部分中所綁定的元件中傳入資訊,則預設將會顯示<slot></slot>所包含的資料:

<div id="app">
    {{ message }}
    <child-element>
        
    </child-element>
</div>
Vue.component('child-element', {
  template:
  `
  <div>
    <slot>Hello Vue!</slot>
  </div>
  `,
  data(){
    return {
      childMessage : 'child component'
    }
  }
})


let vm = new Vue({
  el:'#app',
  data:{
    message : 'parent component'
  }
})

最後顯示的結果會是 <div>Hello Vue!</div>

指定slot

當今天 slot 所要傳入的對象越來越多時,可以透過指定插入的方式去分配 slot 要怎麼對應資料,方法是在子元件中使用 template 標籤並加上v-slot屬性,v-slot的值會對應到的是 slot 標籤的 name 屬性,這樣一來當我們有需要放多個 slot 時就不必擔心對應位置的問題,範例如下:

HTML部分:

<div id="app">
    {{ message }}
    <child-element>
        <template v-slot:first>First</template>
        <template v-slot:second>Second</template>
        <template v-slot:third>Third</template>
    </child-element>
</div>

JavaScript部分:

Vue.component('child-element', {
  template:
  `
  <div>
    <slot name="first"></slot>
    <slot name="second"></slot>
    <slot name="third"></slot>
  </div>
  `,
  data(){
    return {
      childMessage : 'child component'
    }
  }
})


let vm = new Vue({
  el:'#app',
  data:{
    message : 'parent component'
  }
})

最後 HTML 部分子元件的內容將會對應的傳入子元件中,並顯示出來。而這個 API 好用的地方在於今天有個元件我們純粹只是想要更換部分的顯示內容,就可以在父元件引入該子元件,並且透過 v-slot 直接傳入子元件中,而不用資料整筆 props 進去再接出來。

以上是目前 Vue.js 的最後一章節,而實作的部分將會等到我們以 Vue-cli 創建環境時,再搭配 D3.js 一起介紹!

隨文附上今日的黑黑,據家人說他今天在同個地方躺了連續八小時 ( XD???
https://ithelp.ithome.com.tw/upload/images/20190917/20119062Gz4i7Zt1Ic.jpg


上一篇
[ Vue.js ] 狀態保留 keep-alive
下一篇
[ D3.js ] Why D3.js: D3.js 是什麼?
系列文
「小孩才做選擇,我全都要。」小白也能輕鬆瞭解的 Vue.js 與 D3.js 。37
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

2
Kuro Hsu
iT邦新手 1 級 ‧ 2019-09-18 11:34:34

所以什麼時候用 slot 什麼時候用 props ? XD

Amigo iT邦新手 5 級 ‧ 2019-09-18 17:44:30 檢舉

剛好知道,代打一下: 在組件化過程中,客製化的組件可以預留"參數"和"畫面"給呼叫者"替換",前者是用props傳入,後者則是用slot

ShawnL iT邦新手 1 級 ‧ 2019-09-19 12:09:10 檢舉

嗨,89070157 你好,感謝你的回覆。

個人使用 slot經驗尚不多,雖然 89070157 已經提供了一個很簡潔的概念,但我還是想試著從一些文章中汲取資訊參考練習回覆,若有誤還請多多指教:

我認為當一個子元件需要提供欄位讓其他人傳入其他元件、客製化的內容時便會需要使用到 slot,好處是在子元件內部的程式碼容易閱讀,內部不會有過多的條件判斷與資料處理,並且高度客製化也可以使子元件重複利用性更高,例如**光箱(lightbox)**元件就很適合使用 slot 來做為一個空殼以供其他元件傳入。

而若是因需在不同的區塊重複利用而製成的元件,子元件欄位本身不想暴露太多資訊給父層元件,並且該欄位沒有畫面、傳入元件的需求則可以使用 props ,並且可以透過 props check 來檢查傳入的資料類別使否符合子元件本身使用的需求。

以上是我的想法以及 閱讀的文章以供參考。/images/emoticon/emoticon41.gif

Amigo iT邦新手 5 級 ‧ 2019-09-19 17:14:36 檢舉

謝謝版主。雖然slot也可以傳值進去給組件,從這個角度切入slot和props功能似乎一樣,但從slot傳進去的值無法用vue"操作",也就是說並沒有辦法設一個變數值承接然後使用它。所以slot還是回歸"客製化畫面"的用途,就不會和props混淆

我要留言

立即登入留言