摘要:結(jié)構(gòu)項(xiàng)目結(jié)構(gòu)如下,負(fù)責(zé)外層封裝,負(fù)責(zé)事件綁定與渲染控制。節(jié)點(diǎn)通過(guò)決定事件綁定情況,即通過(guò)屬性綁定事件情況,事件控制組件的屬性,這里就不詳細(xì)說(shuō)了。為隱藏狀態(tài)下的添加的,并包裹懶加載組件。
引言
antd的Tooltip組件在react-componment/trigger的基礎(chǔ)上進(jìn)行封裝,而組件Popover和Popconfirm是使用Tooltip組件的進(jìn)行pop,在react-componment中,使用到組件tc-trigger的還有menu、select、dropdown、time-picker、calendar等,本文主要對(duì)tc-trigger源碼進(jìn)行解讀。
結(jié)構(gòu)項(xiàng)目結(jié)構(gòu)如下:
index.js,負(fù)責(zé)外層封裝,負(fù)責(zé)事件綁定與dom渲染控制。
LazyRenderBox.js,pop內(nèi)容懶加載warp。
mock.js 未使用。
Popup.js,pop的warp,負(fù)責(zé)控制pop的對(duì)齊、動(dòng)畫、寬高。
PopupInner.js,pop內(nèi)容warp。
index.js從render方法入手,需要渲染控制pop顯示的節(jié)點(diǎn)和pop內(nèi)容節(jié)點(diǎn)兩個(gè)節(jié)點(diǎn),而pop內(nèi)容節(jié)點(diǎn)一般渲染到body里面,不屬于控制pop顯示的節(jié)點(diǎn)內(nèi),render方法代碼如下:
const trigger = React.cloneElement(child, newChildProps); if (!IS_REACT_16) { return ({({ renderComponent }) => { this.renderComponent = renderComponent; return trigger; }} ); } let portal; // prevent unmounting after it"s rendered if (popupVisible || this._component || props.forceRender) { portal = ({this.getComponent()} ); } return [ trigger, portal, ];
可以看到,index.js渲染了兩個(gè)節(jié)點(diǎn),trigger和portal,trigger即為通過(guò)事件控制portal顯示狀態(tài)的節(jié)點(diǎn),如果react的版本不是16以上,返回ContainerRender組件,ContainerRender組件來(lái)自rc-util,該組件主要做的事情就是使用ReactDOM.unstable_renderSubtreeIntoContainer函數(shù),將pop內(nèi)容渲染到trigger節(jié)點(diǎn)之外,與react16提供的APIcreatePortal作用一致,如果是React16,返回了Portal組件,該組件正是利用了createPortal,將組件渲染到特定的dom節(jié)點(diǎn)內(nèi),但是不管是不是react16,都進(jìn)行了pop渲染的判斷,即popupVisible || this._component || props.forceRender,如果portal不顯示且不強(qiáng)制第一次渲染forceRender,portal將不會(huì)被渲染到dom中,直到判斷為真。
trigger節(jié)點(diǎn)通過(guò)props決定事件綁定情況,即通過(guò)props.trigger屬性綁定事件情況,事件控制Popup組件的visible屬性,這里就不詳細(xì)說(shuō)了。
Popup.js該組件是pop的warp,渲染在trigger節(jié)點(diǎn)之外,通過(guò)ReactDOM.unstable_renderSubtreeIntoContainer或createPortal指定渲染的目標(biāo)節(jié)點(diǎn),也是render方法入手:
render() { return ({this.getMaskElement()} {this.getPopupElement()}); }
返回兩個(gè)內(nèi)容,getMaskElement獲取遮罩,getPopupElement返回Pop節(jié)點(diǎn),getMaskElement這里就不說(shuō)了,渲染的視覺效果,綁定了控制pop節(jié)點(diǎn)的事件。
getPopupElement返回pop節(jié)點(diǎn),render返回代碼如下:
{children}
Animate來(lái)自組件rc-animate,主要負(fù)責(zé)顯示狀態(tài)切換時(shí)候的動(dòng)態(tài)效果,其中原理是監(jiān)聽控制狀態(tài)變化的prop屬性,即代碼中的showProp="xVisible",當(dāng)狀態(tài)變化的時(shí)候,延時(shí)改變dom的class,一般會(huì)有三個(gè)狀態(tài),分別表示進(jìn)入中enter-active,消失中l(wèi)eave-active,隱藏hidden三個(gè)狀態(tài),進(jìn)入中狀態(tài)會(huì)添加transitionName-enter transitionName-enter-active兩個(gè)class,消失中會(huì)添加transitionName-leave transitionName-leave-active兩個(gè)class,隱藏狀態(tài)不添加class,transitionName通過(guò)外部傳入。
Align來(lái)自組件rc-align,主要控制節(jié)點(diǎn)的相對(duì)于trigger的顯示位置,根據(jù)傳入的target與align決定最后PopupInner顯示的位置,此處target是來(lái)自于index.js的trigger節(jié)點(diǎn),align也是來(lái)自于index.js,主要由index.js的prop.popupPlacement、prop.popupAlign兩個(gè)屬性決定,即方向與偏移量。
最后是PopupInner組件,該組件是也就pop內(nèi)容組件,內(nèi)容通過(guò)LazyRenderBox包裹。。。
另外,Popup.js還有兩個(gè)state,targetWidth與targetHeight,即pop的寬高,該屬性如果設(shè)置有prop.stretch,則計(jì)算trigger真是dom節(jié)點(diǎn)的寬高,然后對(duì)齊。
PopupInner.js為隱藏狀態(tài)下的pop添加hidden的class,并包裹懶加載組件LazyRenderBox。
LazyRenderBox.js只做一件事情,就是將popupInner的chidren進(jìn)行包裹,當(dāng)子節(jié)點(diǎn)數(shù)大于1時(shí),包一層div以方便隱藏狀態(tài)時(shí)候class控制,不用每個(gè)節(jié)點(diǎn)都添加hidden的class,關(guān)鍵如下:
render() { const { hiddenClassName, visible, ...props } = this.props; if (hiddenClassName || React.Children.count(props.children) > 1) { if (!visible && hiddenClassName) { props.className += ` ${hiddenClassName}`; } return ; } return React.Children.only(props.children); }最后
該組件主要的實(shí)現(xiàn)難點(diǎn)在于rc-animate與rc-align,其他的主要在做事件綁定與class處理。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107737.html
摘要:引言看過(guò)源碼的都知道,其實(shí)是在一組組件的基礎(chǔ)上進(jìn)行了一層封裝,本文主要解讀組件的基礎(chǔ)組件,另外會(huì)略過(guò)模式下的代碼。解讀源碼首先要從自己最常用的或者感興趣的入手,首先組件最主要的還是在這個(gè)裝飾器入手。 引言 看過(guò)antd源碼的都知道,antd其實(shí)是在一組react-componment組件的基礎(chǔ)上進(jìn)行了一層ui封裝,本文主要解讀antd組件Form的基礎(chǔ)組件react-componmen...
摘要:作為開發(fā)當(dāng)中使用相對(duì)頻繁的一個(gè)組件,其實(shí)現(xiàn)也很簡(jiǎn)單,但是其中比較麻煩的一部分是字體的制作,可以參看這篇文章。接口中的種屬性方法,不屬于上述六種。為事件屬性,可以大家也可以根據(jù)上面所提供的制作的方法和這樣的方式來(lái)實(shí)現(xiàn)自己的組件 Icon icon作為開發(fā)當(dāng)中使用相對(duì)頻繁的一個(gè)組件,其實(shí)現(xiàn)也很簡(jiǎn)單,但是其中比較麻煩的一部分是icon字體的制作,可以參看這篇文章。 Antd的Icon組件使用...
github: 地址gitbook: 地址 Index.js 看一個(gè)代碼的時(shí)候首先當(dāng)然是從他的入口文件開始看起,所以第一份代碼我們看的是/index.js文件 開始 打開index.js文件,代碼只有28行,其中包含了一個(gè)camelCase函數(shù)(看函數(shù)名就知道這是個(gè)給名稱進(jìn)行駝峰命名法的函數(shù)),一個(gè)req變量,以及這個(gè)的變量操作和export操作 在這個(gè)文件里面我首先查了require.conte...
摘要:這個(gè)組件是一個(gè)圖釘組件,使用的布局,讓組件固定在窗口的某一個(gè)位置上,并且可以在到達(dá)指定位置的時(shí)候才去固定。 Affix 這個(gè)組件是一個(gè)圖釘組件,使用的fixed布局,讓組件固定在窗口的某一個(gè)位置上,并且可以在到達(dá)指定位置的時(shí)候才去固定。 AffixProps 還是老樣子,看一個(gè)組件首先我們先來(lái)看看他可以傳入什么參數(shù) // Affix export interface Affix...
Button Button包括了兩個(gè)組件,Button與ButtonGroup。 ButtonProps 看一個(gè)組件首先看的是他的傳參也就是props,所以我們這里先看Button組件的ButtonProps export type ButtonType = primary | ghost | dashed | danger; export type ButtonShape = circl...
閱讀 2706·2021-11-18 10:02
閱讀 3470·2021-09-22 15:50
閱讀 2390·2021-09-06 15:02
閱讀 3607·2019-08-29 16:34
閱讀 1771·2019-08-29 13:49
閱讀 1310·2019-08-29 13:29
閱讀 3682·2019-08-28 18:08
閱讀 3009·2019-08-26 11:52