[譯] 我最終是怎麼玩轉了 Vue 的做用域插槽

Vue 是一個用於構建 Web 應用程序的前端框架,其設計方式使得開發人員能夠很是快速地提升工做效率。該框架的各個方面都有不少資料,它的社區也天天都在不斷成長。若是你讀到了這篇文章,那麼這些事兒你極可能已經知道咯。前端

雖然咱們能夠快速直接地啓動並運行它,可是框架裏面那些更復雜和更強大的地方仍是須要好好動動腦子才能理解(至少對我是這樣)。其中一個是插槽,還有另外一個與之相關但功能上不太相同的就是做用域插槽。我學習的時候花了好一陣才理解插槽工做的機制,因此我以爲將我對插槽的理解分享出來是有價值的,由於這沒準會幫助到你們。vue

插槽和具名插槽

父組件以另一種方式(不是經過常規的 Props 屬性傳遞機制)向子組件傳遞信息。我發現把這種方法同常規的 HTML 元素聯繫起來頗有幫助。android

好比說 HTML 標籤。ios

<a href=」/sometarget">This is a link</a> 複製代碼

若是這是在 Vue 環境中而且<a>是你的組件,那麼你須要發送「This is a link」信息到‘a’組件裏面,而後它將被渲染成爲一個超連接,而「This is a link」就是這個連接的文本。git

讓咱們定義一個子組件來展現它的機制是怎樣的:github

<template>  
  <div>  
    <slot></slot>  
  </div>  
</template>
複製代碼

而後在父組件咱們這麼作:後端

<template>  
  <div>  
    <child-component>This is from outside</child-component>  
  </div>  
</template>
複製代碼

這時候屏幕上呈現的就應該和你預期的同樣就是「This is from outside」,但這是由子組件所渲染出來的。bash

咱們還能夠給子組件添加默認的信息,以避免到時候這裏出現什麼都沒有傳入的狀況,就像這樣子:前端框架

<template>  
  <div>  
    <slot>Some default message</slot>  
  </div>  
</template>
複製代碼

而後若是咱們像這樣子建立咱們的子組件:框架

<child-component>  
</child-component>
複製代碼

咱們能夠看到屏幕上會呈現「Some default message」。

具名插槽和常規插槽很是相似,惟一的差異就是你能夠在你的目標組件多個位置傳入你的文本。

咱們把子組件升級一下,讓它有多個具名插槽

<template>  
  <div>  
    <slot>Some default message</slot>  
    <br/>  
    <slot name="top"></slot>  
    <br/>  
    <slot name="bottom"></slot>  
  </div>  
</template>
複製代碼

這樣,在咱們的子組件中就有了三個插槽。其中 top 和 bottom 插槽是具名插槽。

讓咱們更新父組件以使用它。

<child-component v-slot:top>  
Hello there!  
</child-component>
複製代碼

注意 —— 咱們在這裏使用新的 Vue 2.6 語法來指定咱們想要定位的插槽:`v-slot:theName`。

你如今認爲會在屏幕上看到什麼呢?若是你說是「Hello Top!」,那麼你就只說對了一部分。

由於我沒有爲沒有具名的插槽賦予任何值,咱們所以也還會獲得默認值。因此咱們真正會看到的是:

Some default message
Hello There!

其實真正意義上沒有具名的插槽是被看成‘default’,因此你還能夠這麼作:

<child-component v-slot:default>  
Hello There!  
</child-component>
複製代碼

如今咱們就只會看到:

Hello There!

由於咱們已經提供了值給默認(也就是未具名)插槽,所以具名插槽‘top’和‘bottom’也都沒有默認值。

你發送的並不必定只是文本,還能夠是其餘組件或者 HTML。你能夠發送任意你想展現的內容。

做用域插槽

我認爲插槽和具名插槽相對簡單,一旦你稍微玩玩就能夠掌握。可另外一方面,做用域插槽雖然名字類似但又有些不一樣之處。

我傾向於認爲做用域插槽有點像一個放映機(或者是一個我歐洲朋友的投影儀)。如下是緣由。

子組件中的做用域插槽能夠爲父組件中的插槽的顯示提供數據。這就像一我的帶着放映機站在你的子組件裏面,而後在父組件的牆上讓一些圖像發光。

這有一個例子。在子組件中咱們像這樣設置了一個插槽:

<template>  
  <div>  
    <slot name="top" :myUser="user"></slot>  
    <br/>  
    <slot name="bottom"></slot>  
    <br/>  
  </div>  
</template>

<script>

data() {  
  return {  
    user: "Ross"  
  }  
}

</script>
複製代碼

注意到咱們的具名插槽‘top’如今有了一個名爲‘myUser’的屬性,而後咱們綁定了一個動態的值在‘user’中。

在咱們的父組件中就像這樣子設置子組件:

<div>  
   <child-component v-slot:top="slotProps">{{ slotProps }}</child-component>  
</div>
複製代碼

咱們在屏幕上看到的就是這樣子:

{ 「myUser」: 「Ross」 }

仍是使用放映機的類比,咱們的子組件經過 myUser 對象將其用戶字符串的值傳遞給父組件。它在父組件上投射到的牆就被稱爲‘slotProps’。

我知道這不是一個完美的類比,但當我第一次嘗試理解這個機制的時候,它幫助我以這種方式思考。

Vue 的文檔很是好,並且我也已經看到了一些其餘關於做用域插槽工做機制的說明。但不少人採起的方法彷佛是將父組件中的全部或部分屬性命名爲與子組件相同,我認爲這會使得數據很難被追蹤。

在父組件中使用 ES6 解構,咱們這樣子寫還能夠將特定 user 對象從插槽屬性(你能夠隨便怎麼稱呼它)解脫出來:

<child-component v-slot:top="{myUser}">{{ myUser }}</child-component>
複製代碼

或者甚至就只是在父組件中給它一個新的名字:

<child-component v-slot:top="{myUser: aFancyName}">{{ aFancyName }}</child-component>
複製代碼

全部都是經過 ES6 解構,與 Vue 自己並無什麼關係。

若是你正開始使用 Vue 和插槽,但願這可讓你起步並解決一些棘手的問題。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索