摘要:返回刪除的節(jié)點。組件運行邏輯此時,組件的代碼與邏輯已經(jīng)全部分析完了,整個組件的運行邏輯可以通過下方這張圖來概括本篇完
Wave組件效果預(yù)覽
???????在上一篇文章Button組件的源碼分析中遇到了一個Wave組件, Wave組件在Ant design中提供了通用的表單控件點擊效果,在自己閱讀源碼之前,也并沒有過更多留心過在這些表單控件的動畫效果是如何實現(xiàn)的,甚至可能有時都沒注意到這些動畫效果。下面先一起來看以下具體的效果(留意邊框以外,一閃一閃的波浪動畫效果):
Button組件
Radio組件
Switch組件
???????看完UI效果之后我們大概已經(jīng)知道是什么了,再看代碼部分,由于代碼書寫順序與閱讀順序并不一致,為了方便理解,我們在分析源碼的過程中,會調(diào)整代碼解釋的順序
源碼分析// 一個新的依賴,暫時不知道是什么,依據(jù)名字推測與動畫效果有關(guān) import TransitionEvents from "css-animation/lib/Event"; export default class Wave extends React.Component<{insertExtraNode?: boolean}> { //... some type code // 我們發(fā)現(xiàn)Wave組件只提供組件邏輯,不參與UI展示,這種容器組件,往往在DidMount或WillMount聲明周期中開始 // 構(gòu)建組件邏輯,往下看 render() { return this.props.children; } // 只有一行代碼, 先看下方bindAnimationEvent方法 componentDidMount() { this.instance = this.bindAnimationEvent(findDOMNode(this) as HTMLElement); } // 在組件卸載時,清除掉事件監(jiān)聽與定時器,避免內(nèi)存泄漏 componentWillUnmount() { if (this.instance) { this.instance.cancel(); } if (this.clickWaveTimeoutId) { clearTimeout(this.clickWaveTimeoutId); } } // 根據(jù)名字推測: 為DOM節(jié)點綁定動畫效果,進入函數(shù)內(nèi)部查看 bindAnimationEvent = (node: HTMLElement) => { //... some code const onClick = (e: MouseEvent) => { //... some code // 無論是否正在執(zhí)行動畫,先清除掉動畫效果(至于怎么清除,先不關(guān)注) this.resetEffect(node); // 從target取得顏色值 const waveColor = getComputedStyle(node).getPropertyValue("border-top-color") || // Firefox Compatible getComputedStyle(node).getPropertyValue("border-color") || getComputedStyle(node).getPropertyValue("background-color"); // 在這里可以看到之前定義的私有變量clickWaveTimeoutId,被用作儲存一個定時器 this.clickWaveTimeoutId = window.setTimeout(() => this.onClick(node, waveColor), 0); }; // 監(jiān)聽node(this.props.children)的onClick事件 node.addEventListener("click", onClick, true); // 將移除監(jiān)聽事件的回調(diào)函數(shù)封裝在一個對象中并作為返回值,看著這里應(yīng)該想起之前定義的私有變量instance, // 回顧DidMount生命周期函數(shù),你會發(fā)現(xiàn)這個返回的對象將會被儲存在instance中 return { cancel: () => { node.removeEventListener("click", onClick, true); }, }; } //未完待續(xù)
我們通過觀察上方bindAnimationEvent方法,其主要做了三件事,調(diào)用了兩個外部函數(shù)this.resetEffect 與 this.onClick
1、過濾不執(zhí)行的條件(代碼省略掉了,非主干邏輯)
2、聲明onClick函數(shù),并作為node的點擊事件觸發(fā)時要執(zhí)行的函數(shù)
3、返回一個儲存了取消監(jiān)聽click事件方法的對象
個人認(rèn)為bindAnimationEvent方法,做了太多的事情,而ComponentDidMount做的事情太少(單一原則)
往下方,繼續(xù)查看 this.resetEffect 與 this.onClick 分別是做什么的,以及如何實現(xiàn)的
// 這個函數(shù)是實現(xiàn)動畫效果的核心,其主要有三個行為:1、創(chuàng)建內(nèi)聯(lián)style標(biāo)簽, 2、插入css字符串 3、并將其插入到document中 // 我們知道css也是可以控制DOM變化的,比如偽類元素:after :before 這里正是通過:after來實現(xiàn)效果的 onClick = (node: HTMLElement, waveColor: string) => { //... some code 1 const { insertExtraNode } = this.props; /* 創(chuàng)建了一個div元素extraNode,裝飾該div,在inserExtracNode= true時,將extraNode作為node的子元素 */ /* 創(chuàng)建一個div元素,并緩存中私有變量extraNode中 */ this.extraNode = document.createElement("div"); /* 這里用let 更合適 */ const extraNode = this.extraNode; extraNode.className = "ant-click-animating-node"; // 可能有人好奇這個extraNode是干嘛的? // 往之后的代碼中看的時候會發(fā)現(xiàn),在insertExtraNode為false時,Wave通過插入偽類元素:after 來作為承載動畫效果的DOM元素 // 在insertExtraNode = true時,會生成一個div替代:after偽類元素,猜測是某些this.props.children可能自帶:after,所以 // 使用div元素來替代:after避免沖突,在這里我們只需要知道它是作為承載動畫css的DOM元素即可 // 獲取指定的string insertExtraNode ? "ant-click-animating" : "ant-click-animating-without-extra-node"; const attributeName = this.getAttributeName(); // Element.removeAttribute("someString"); 從element中刪除值為someString的屬性 // Element.setAttribute(name, value); 為element元素值為value的name屬性 node.removeAttribute(attributeName); node.setAttribute(attributeName, "true"); // 行為1:這里創(chuàng)建了一個內(nèi)聯(lián)style標(biāo)簽 styleForPesudo = styleForPesudo || document.createElement("style"); if (waveColor && waveColor !== "#ffffff" && waveColor !== "rgb(255, 255, 255)" && this.isNotGrey(waveColor) && /* 透明度不為0的任意顏色 */ !/rgba(d*, d*, d*, 0)/.test(waveColor) && // any transparent rgba color waveColor !== "transparent") { /* 給子元素加上borderColor */ extraNode.style.borderColor = waveColor; /* 行為2:在內(nèi)聯(lián)style標(biāo)簽中插入樣式字符串, 利用偽元素:after作為承載效果的DOM */ styleForPesudo.innerHTML = `[ant-click-animating-without-extra-node]:after { border-color: ${waveColor}; }`; /* 行為3:將style標(biāo)簽插入到document中 */ if (!document.body.contains(styleForPesudo)) { document.body.appendChild(styleForPesudo); } } /* 在inserExtarNode為true時,將extraNode插入到node子元素中 */ if (insertExtraNode) { node.appendChild(extraNode); } /* 為元素增加動畫效果 */ TransitionEvents.addEndEventListener(node, this.onTransitionEnd); } /** * 重置效果 * 顧名思義:這個函數(shù)通過三個行為,致力于一件事情,取消動畫效果 * 1、刪除node的attribute屬性 2、node的子元素 3、刪除對應(yīng)的內(nèi)聯(lián)style標(biāo)簽 */ resetEffect(node: HTMLElement) { // come code ... const { insertExtraNode } = this.props; const attributeName = this.getAttributeName(); /* 行為1:刪除node的attribute屬性 */ node.removeAttribute(attributeName); /* 行為3: 清空了為偽類元素內(nèi)置的style標(biāo)簽 styleForPesudo */ this.removeExtraStyleNode(); if (insertExtraNode && this.extraNode && node.contains(this.extraNode)) { // Node.removeChild() 方法從DOM中刪除一個子節(jié)點。返回刪除的節(jié)點。 node.removeChild(this.extraNode); } TransitionEvents.removeEndEventListener(node, this.onTransitionEnd); } // 刪除內(nèi)聯(lián)style標(biāo)簽 removeExtraStyleNode() { if (styleForPesudo) { styleForPesudo.innerHTML = ""; } } // 在每次動畫執(zhí)行結(jié)束后,清除掉狀態(tài),完成一個生命周期 onTransitionEnd = (e: AnimationEvent) => { // todo if (!e || e.animationName !== "fadeEffect") { return; } this.resetEffect(e.target as HTMLElement); } }組件邏輯:
我們回過頭來看第一部分的代碼,組件邏輯體現(xiàn)在componentDidMount 與 componentWillUnMount中
1、在componentDidMount中為this.props.children的click事件綁定動畫執(zhí)行函數(shù)this.onClick,
2、在componentWillUnMount中清除與動畫相關(guān)的狀態(tài)避免內(nèi)存泄漏。
此時,Wave組件的代碼與邏輯已經(jīng)全部分析完了,整個Wave組件的運行邏輯可以通過下方這張圖來概括
本篇完~
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/102079.html
摘要:通過將實例傳入回調(diào)函數(shù)。添加再回過頭來看回調(diào)函數(shù)的內(nèi)容。其中的作用是一次調(diào)用傳入的各函數(shù),其中方法是移除中相應(yīng)的節(jié)點,是傳入的關(guān)閉標(biāo)簽后的回調(diào)函數(shù)。 notification簡介 showImg(https://segmentfault.com/img/remote/1460000014117558?w=483&h=135); notification就是通知提醒框,在系統(tǒng)四個角顯示通...
摘要:擅長網(wǎng)站建設(shè)微信公眾號開發(fā)微信小程序開發(fā)小游戲制作企業(yè)微信制作建設(shè),專注于前端框架服務(wù)端渲染技術(shù)交互設(shè)計圖像繪制數(shù)據(jù)分析等研究。 Ant Design of React @3.10.9 拉取項目 luwei.web.study-ant-design-pro, 切換至 query 分支,可看到 Form 表單實現(xiàn)效果 實現(xiàn)一個查詢表單 showImg(https://segmentfau...
摘要:前言一直混跡社區(qū)突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點混亂所以將前端主流技術(shù)做了一個書簽整理不求最多最全但求最實用。 前言 一直混跡社區(qū),突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點混亂; 所以將前端主流技術(shù)做了一個書簽整理,不求最多最全,但求最實用。 書簽源碼 書簽導(dǎo)入瀏覽器效果截圖showImg(https://segmentfault.com/img/bVbg41b?w=107...
摘要:使用官方的的另外一種版本和一起使用自動配置了一個項目支持。需要的依賴都在文件中。帶靜態(tài)類型檢驗,現(xiàn)在的第三方包基本上源碼都是,方便查看調(diào)試。大型項目首選和結(jié)合,代碼調(diào)試維護起來極其方便。 showImg(https://segmentfault.com/img/bVbrTKz?w=1400&h=930); 阿特伍德定律,指的是any application that can be wr...
閱讀 929·2021-11-16 11:45
閱讀 2134·2021-10-09 09:44
閱讀 1353·2019-08-30 14:03
閱讀 1138·2019-08-26 18:28
閱讀 3338·2019-08-26 13:50
閱讀 1727·2019-08-23 18:38
閱讀 3458·2019-08-23 18:22
閱讀 3604·2019-08-23 15:27