- 原文地址:How I finally got my head around Scoped Slots in Vue
- 原文作者:Ross Coundon
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:shixi-li
- 校對者:brilliantGuo, xionglong58
Vue 是一個用於構建 Web 應用程式的前端框架,其設計方式使得開發人員可以非常快速地提高工作效率。該框架的各個方面都有很多資料,它的社群也每天都在不斷成長。如果你讀到了這篇文章,那麼這些事兒你很可能已經知道咯。
雖然我們可以快速直接地啟動並執行它,但是框架裡面那些更復雜和更強大的地方還是需要好好動動腦子才能理解(至少對我是這樣)。其中一個是插槽,還有另一個與之相關但功能上不太相同的就是作用域插槽。我學習的時候花了好一陣才理解插槽工作的機制,所以我覺得將我對插槽的理解分享出來是有價值的,因為這沒準會幫助到大家。
插槽和具名插槽
父元件以另外一種方式(不是通過常規的 Props 屬性傳遞機制)向子元件傳遞資訊。我發現把這種方法同常規的 HTML 元素聯絡起來很有幫助。
比如說 HTML 標籤。
<a href=”/sometarget">This is a link</a>
複製程式碼
如果這是在 Vue 環境中並且<a>是你的元件,那麼你需要傳送“This is a link”資訊到‘a’元件裡面,然後它將被渲染成為一個超連結,而“This is a link”就是這個連結的文字。
讓我們定義一個子元件來展示它的機制是怎樣的:
<template>
<div>
<slot></slot>
</div>
</template>
複製程式碼
然後在父元件我們這麼做:
<template>
<div>
<child-component>This is from outside</child-component>
</div>
</template>
複製程式碼
這時候螢幕上呈現的就應該和你預期的一樣就是“This is from outside”,但這是由子元件所渲染出來的。
我們還可以給子元件新增預設的資訊,以免到時候這裡出現什麼都沒有傳入的情況,就像這樣子:
<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 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。