確定API
- 要確保你的API和同行的API沒有太大不同,否則用戶學習成本變高,不利于我們的UI使用;所以我們就可以去copy下同行的API;
- 提供兩種風格:一是標簽風格,二是API風格
- 創建dialog目錄;
搭建Dialog 基本架子
-
<Fragment></Fragment>
用于把多個div包起來,但是在頁面中卻不會渲染出來(有點像<template>),所以經常使用<Fragment></Fragment>
來代替<div></div>
; - 我們需要在每個className上都寫一遍
dui-dialog-
,豈不是很麻煩?!所以我們寫個函數來統一它吧~ - 返回函數的函數叫做高階函數;
添加CSS
- 這里一個小問題,index.scss要引入到example.tsx中樣式才有效!!!!只引入到index.tsx中在預覽例子的時候樣式不起作用!!!!(應該跟生產開發環境文件設置的入口有關)
- 想要svg受外面字體顏色的控制,加上
fill: currentColor;
- 跟字體相關可以用px、em,跟布局寬度相關可以用min-width結合em;
- 屬性選擇器,
[class^=xx]
代表所有以xx開頭的類;
添加事件
1、可以自定義按鈕
- 給dialog一個buttons Props,它是個數組;
- 所以這時又有個小警告了,因為是個數組,需要給每一項設置key,就用到了
React.cloneElement
; - 為什么用
React.cloneElement
,而不是直接button['key'] = index
這樣添加屬性呢,因為報錯啊!!!說不能給只讀屬性key賦值啊!!!
2、給組件的props設置默認值
Dialog.defaultProps = {
closeonClickMask: false
}
- 一般設置過默認值后,這個props就是可選的,
interface
屬性那里加上?
;
3、ReactDOM.createPortal
- ReactDOM.createPortal,這是由于層級問題引起的,給dialog的層級越小越好,這樣也方便用戶自己去改;
- 一般網站架構師會設定好層級
-
可以在文檔中告訴開發者,你如何寫可以覆蓋我的層級;
image.png
注意:為了禁止遮罩層來回滑動,在對話框出現的時候
document.body.style.overflow='hidden'
和document.body.style.paddingRight = '17px'
,關閉的時候恢復document.body.style.overflow='auto'
和document.body.style.paddingRight = '0'
給Dialog提供便利的API——alert
- 動態創建組件,即用
ReactDOM.render()
把組件渲染進div; - 關閉組件呢,即還是用
ReactDOM.render()
渲染組件,只不過是把組件的visible屬性變成false; -
ReactDOM.unmountComponentAtNode()
,文檔
//創建組件和節點
const div = document.createElement("div");
document.body.appendChild(div);
document.body.style.overflow = 'hidden'
ReactDOM.render(component, div);
//消除組件和節點
//第一句:把這個組件的visible改成false
ReactDOM.render(React.cloneElement(component, {visible: false}), div)
//第二句:把這個組件從div上卸載下來
ReactDOM.unmountComponentAtNode(div)
document.body.style.overflow = 'auto'
//第三句:清除這個div
div.remove()
comfirm
modal
- ReactElement和ReactNode區別:ReactElement只能是標簽元素,ReactNode還可以是字符串;
- modal return一個函數出來,有點類似于閉包的形式;
- 下面代碼中button調用函數的形式,要寫一個箭頭函數去調用close(這個close函數是modal()return出來的函數),直接
onClick={close}
的話是不可以的,因為解析器是從右往左執行的,這樣直接寫,它找不到你聲明的close在哪里,放在箭頭函數中就可以的原因是,函數是延遲執行的,只有點擊按鈕時才調用函數; 所以在聲明函數的時候不要直接去調用它本身!!!
const openModal = () => {
const close = modal(
<div>
<h1>你好</h1>
<button style={{ color: "purple" }} onClick={() => close()}>
close
</button>
</div>
);
};
三者之前的區別
1、是否有按鈕
- alert只有一個【確認】按鈕,按鈕沒有回調函數;
- comfirm有【取消】、【確認】按鈕,且按鈕有各自的回調函數;
- modal沒有按鈕;
2、傳的內容
- alert和comfirm傳的內容僅僅是字符串;
- modal不僅可以傳字符串,還可以傳元素,但要保證只有一個根元素;
重構
image.png
- 寫完代碼請立即重構,消除重復的代碼;
- 看上圖,抽出每個API中的part,可以看出它們的組成很相近,所以可以把它們寫成一個公共的函數;
總結
- scopedClass 高階函數;
- React.Fragment
- 使用
&&
或者三元表達式來做條件判斷,一般不用if...else...來寫條件判斷,有點麻煩; -
ReactDOM.createPortal
傳送門,可以使元素脫離當前位置到達你指定的節點位置; - 如何動態去生成一個組件;
- 閉包傳API;