開始之前,先說一下 Portal 其實是 React 比較常用的 Pattern,因此非 React 使用者可以斟酌一下怎麼去理解這個 Interface。
Vue 是在第三版之後才實現了這個功能,在此之前都是以 Dialogs 這個元件來滿足下面會提到的 Portal、Popper、Popconfirm 的使用情境。
而 Angular 則是原本的 template 語法就已經能滿足 Portal 所需要的功能,因而不會特別去實作 Portal 和 Popper,它在 Material 上會跟 Vue 一樣實作 Dialogs ,而在 Ant Design 則是有去實作 Popconfirm。
由於「傳送」這個功能可以用在很多地方,因此 Portal 也可以是一個 interface ,透過 UML 來看 Portal 相關的依賴關係大概會長這樣,當然要不要照這種方式去建構這些元件也是很看使用情境的,那以下會來簡單介紹一下各個 Component。
先來看看 Portal 長怎樣:
How to use
Portal 的作用是讓元件脫離原本的 DOM 結構,子元件可以傳送到父元件以外的任意地方,可以把它想像成一個元素的「傳送門」,要傳送到的地方叫 container。
沒有 container 的情況下,子元素會 render 到與 root 同層的位置。
有給的話 Element 會 render 到 container 之下,接下來直接看看 Materiel-UI 的範例 ,相信就會清楚很多了。
看到 Popper 時,大家可能會好奇 Popper 跟 Portal 的差別在哪?
Portal 是單純在實現「傳送」這個功能,是一個沒有樣式,單純能把子元素傳送出去的元件。
Popper 則是去包裝 Portal,在 Portal 提供了「傳送」這個功能之後,進一步地去定位元素要出現的位置(anchorEl ),就像圖中是能讓 Popper 出現在 Toggle Popper 這個按鈕下面。
這邊要做的處理是「確保 Popper children 能有正常顯示的空間」,出現要的位置、與錨定的 Element 要保持多少距離等等。
沒有給 anchorEl 的話,預設錨定 Element 是 body , Popper 會出現在左上方(因為沒有東西可以定位)。
有給的話 錨定 Element 就會是給定的那個 Element, Popper 會根據該 Element 定位在他的上下左右。
Popover 是有「標題」與「內容」版的 Popper,是在 Popper 的基礎上,給定常用樣式的 UI 元件。
雖然看起來沒什麼,但如果專案中有很多 Popover 的使用情境的話,切出來絕對是不吃虧的。
如果真的要省通常也是會省掉 Popper ,而不是 Popover ,鑑於 Material-UI、Ant Design 和 Chakra-UI 都有 Popover,但只有 Material-UI 特別拆了 Popper 這一層來判斷。
How to use
從 Popover 再往前走一步,把 children 包成「確認」和「取消」這兩個按鈕,主要使用情境就像是附圖那樣,通常是在使用者想做一些重要的操作(如:取消)時,能再確認一次。
需要注意的是元件分類的部分,Popconfirm 與 Popper 和 Popover 不一樣,會被歸類到 Feedback ,主要是讓使用者做某些動作時,有一個「確認」的回饋,而不像前兩者一樣只是在展示資訊。
那 Poper 和 Popover 的分類就看各個系統怎麼去理解了,可以是 Utils、Data Display 或其他自己定義出來的種類。
How to use
Tooltip 的功能就跟名字一樣,是一種 「提示」,可以在文字或是按鈕上顯示額外的資訊,通常是在滑鼠 Hover 上去的時候觸發,讓你點擊前可以更知道關於這個按鈕的功能,或是顯示文字的別種資訊(中文字顯示英文翻譯 或是 字數過長 ellipsis 的時候顯示剩餘文字 等等)。
How to use
// Material-UI Example
<Tooltip title="Delete">
<IconButton aria-label="delete">
<DeleteIcon />
</IconButton>
</Tooltip>
<Tooltip title="Add" aria-label="add">
<AddIcon />
</Tooltip>
<Tooltip title="Add" aria-label="add">
<AddIcon />
</Tooltip>
// Ant Design Example
<Tooltip title="prompt text">
<span>Tooltip will show on mouse enter.</span>
</Tooltip>
Dropdown 就是一個下拉式選單,它顯示出來的選單也可以是透過 Popper 的方式來脫離原本的 DOM 結構,浮在頁面之上。
而打開跑出來的「選單」也是一個獨立的 UI 元件 - Menu ,但對於它的介紹會放到 Independent 的 UML 介紹。
How to use
<Dropdown
menu={menu}
popperProps={popperProps}
>
Hover me
</Dropdown>
Overlay 就是一層蓋在網頁上的暗色背景,在我們打開 Modal 或是 選單的時候,背景會變色並且不讓使用者進行互動,讓使用者專注在跳出來的那個區塊,可能是輸入帳密的 Modal 或是點開左右的選單。
而因為是要蓋在整個頁面之上,因此也會需要脫離原先的 DOM,透過 Portal 去傳送。
它的樣式會在下面的 Drawer 給大家看!
How to use
<Overlay>
重點操作區塊
</Overlay>
Drawer 就像是抽屜一樣打開一個側邊的選單,比較常見的應用是平板或手機版的 Header,而 Drawer 裏可以是一些表單欄位,也可以單純呈現一些資訊。
(左側那塊黑色濾鏡就是 Overlay 唷!)
How to use
<>
<Button type="primary" onClick={showDrawer}>
Open
</Button>
<Drawer
title="Basic Drawer"
placement="right"
closable={false}
onClose={onClose}
visible={visible}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
</>
Modal 就是一個彈出的框框,讓使用者可以在不跳轉到新頁面的時候「確認資訊」、「填資訊」等等。
在 Material-UI 的 Modal 則是被當作 Dialog、Drawer、Menu 和 Popover 的底層(因此它們的 UML 也會跟上述不太一樣),Modal 跟 Dialog 就像上述的 Popper 跟 Popover 一樣,Modal 是純粹實作有 Overlay 的彈出框功能,而 Dialog 則是有樣式的 Modal,多數時候它們會建議你直接使用 Dialog 而不是底層的 Modal。
我自己是比較喜歡 Ant Design 的作法,而沒有特別去做 Dialog ,都只用 Modal 去組,想怎麼採用或實作都還是看需求。
因為今天的內容也挺多了就不再特別去講 Dialog 了,有興趣的可以去看 Material-UI — Dialog 或 Chakra-UI — Alert Dialog。
How to use
// Material-UI
<button type="button" onClick={handleOpen}>
Open Modal
</button>
<Modal
open={open}
onClose={handleClose}>
{body}
</Modal>
// Chakra-UI
今天的內容可能會有讀者覺得元件切得太細了,這是因為這些是我參考各個元件庫之後,才統整出來的一個系列,所以一般都會稍微取捨一些比較少用到的情境,有些會讓使用者要用時再自己去組,像是 Popper、Popover 和 Popconfirm 這三個幾乎不會同時都被實作出來,至少就 Material-UI、Ant Design 和 Chakra-UI 是都只實作部分。
那今天的重點是在講元件間的依賴關係,所以程式碼只是大概寫一下怎麼用而已,沒有要在這邊深入去講解實作,實作會在 UML 環節介紹完之後才開始,請大家敬請期待囉!
明天要講的是很容易跟 Portal 搞混的 Notifier ,雖然都會脫離本身的 DOM 結構,但背後的機制跟所想提供的功能完全不一樣,至於怎麼不一樣的就先賣個關子啦!
那就明天見啦!