咱們知道在HTML中標籤能夠分爲閉合標籤和空標籤,其中大多數都是閉合標籤,只有少數空標籤,好比:<input/>
、`<img/>
、<base/>
、<hr/>
等。在Vue中定義的組件也能夠採用兩種方式來書寫。html
在一個組件的<template>
中假如顯示一個標題<h1>Hello World!</h1>
,當咱們在調用時,不論是採用<組件名/>
或者<組件名></組件名>
都會顯示 「hello world!「,因爲在閉合標籤中能夠包含子節點和文本,所以咱們能夠這樣來使用<組件名>我是內容</組件名>
,可是運行的結果,確什麼也沒有改變。vue
若是想要在組件傳入的內容正確投射,就須要一套機制來處理,在Vue中天然就是slot(插槽)機制,在React中能夠經過this.props.children
來獲取,而在Angular中能夠經過<ng-content></ng-content>
來放置轉入的內容。git
在React中傳入this.props.children
的值有三種可能:github
undefined
object
array
若是要對傳入的數據進行處理,React還提供了一個工具方法React.Children
來處理this.props.children
。總的來講React把一切處理徹底交給開發人員來,徹底透明。編程
React的這種處理方式相對來講也更加靈活,對於Vue的做用域插槽機制也能很簡單的實現。segmentfault
相對於React的徹底透明模式,Angular則在傳入內容時經過屬性、類(class)和標籤三種模式來區分和限定內容的做用域。在組件內容使用<ng-content select="xx"></ng-content>
來做爲佔位,具休使用方式以下:工具
<div card-body>屬性</div> <ng-content select="[card-body]"></ng-content> <div card-type="body">屬性值</div> <ng-content select="[card-type=body]"></ng-content> <div card body>多個屬性值組合</div> <ng-content select="[card][body]"></ng-content>
<div class=".card-body">類</div> <ng-content select=".card-body"></ng-content> <div class="card body">多個類組合</div> <ng-content select=".card.body"></ng-content>
<card-body></card-body> <ng-content select="card-body"></ng-content>
<ng-content select="header"></ng-content> <div class="body">balabala...</div> <ng-content select="footer"></ng-content>
從上面的使用方式來看Angular的插槽功能仍是很強大的。this
迴歸到本文的主題,在Vue 2.6.0事後引入了新語法機制將之前版本的slot
和scope-slot
使用一個屬性來表示。具體原因可查看其RFC。code
在新的語法中v-slot
只容許使用在 組件 和 <template></template>
標籤中,而且在只能<template>
套組件和子<template>
。htm
在組件中直接放一個<slot></slot>
標籤就能夠接收來自組件中的內容,若是<slot>
不爲空,那麼內容將做爲默認值顯示。
在調用時就可使用v-slot:default
在組件上或者其子節點<template>
上。
具名插槽就是把分佈在頁面中不一樣位置的<slot>
分配一個名字來標識,以區分其功能。在使用時只須要給<slot>
添加一個name
屬性便可,例如:<slot name="footer"></slot>
。在使用時把默認插槽的default
換成相應的名字便可,即:<template v-slot:footer></template>
。
在使用過程沒有必要每次都重複寫v-slot:
,同v-on
和v-bind
同樣,v-slot
也有其縮寫形式,即把參數以前的全部內容 (v-slot:
) 替換爲字符 #
,即<template #footer></footer>
做用域插槽的機制就是被調用的組件把組件內部的狀態經過屬性暴露給當前上下文。簡單點說就是它只提供數據,至於當前數據怎麼展現它不關心,相似於React的Render Props機制。
因爲Vue官方文檔寫得很清楚明白這裏直接上知識點:
<current-user v-slot="{ user }"> {{ user.firstName }} </current-user>
<current-user v-slot="{ user: person }"> {{ person.firstName }} </current-user> <current-user v-slot="{ user = { firstName: 'Guest' } }"> {{ user.firstName }} </current-user>
官方提到在只有默認插槽時可使用插槽的縮寫語法,將v-slot:default="slotProps"
寫成v-slot="slotProps"
,可是在使用時官方也說了不能和具名插槽混用,由於它會致使做用域不明確。
下面經過一個示例來實現React中的Render Props機制。
<template> <div style="height:100%" @mousemove="handleMouseMove"> <p>The current mouse position is {{ x }}, {{ y }}</p> <slot :position="position"/> </div> </template> <script> export default { name: 'Mouse', data() { return { x: 0, y: 0 } }, computed: { position: function() { return { x: this.x, y: this.y } } }, methods: { handleMouseMove(event) { this.x = event.clientX this.y = event.clientY } } } </script>
而後在其它組件中調用
<mouse> <template v-slot:default="{position}"> <img src="http://iph.href.lu/64x64?text=圖片跟隨鼠標" :style="{position: 'absolute', left: position.x + 'px', top: position.y + 'px'}"/> </template> </mouse>
動態插槽歡迎經過編程動態控制當前組件的插槽名,使用方式以下:
<template v-slot:[dynamicSlotName]>...</template>
<foo v-slot="foo"> <bar v-slot="bar"> <baz v-slot="baz"> {{ foo }} {{ bar }} {{ baz }} </baz> </bar> </foo>
本文只是簡單對Vue的Slot的知識點作一個簡單的筆記,更多的知識點官方文檔比較靠譜,文中並無提到在JSX語法下的插槽使用方式,若是想要了解請查看個人另一篇文章Vue中jsx不徹底應用指南關於插槽部分的內容。