亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Ant Design源碼分析(三):Wave組件

luzhuqun / 3672人閱讀

摘要:返回刪除的節(jié)點(diǎn)。組件運(yùn)行邏輯此時(shí),組件的代碼與邏輯已經(jīng)全部分析完了,整個(gè)組件的運(yùn)行邏輯可以通過下方這張圖來概括本篇完

Wave組件效果預(yù)覽

???????在上一篇文章Button組件的源碼分析中遇到了一個(gè)Wave組件, Wave組件在Ant design中提供了通用的表單控件點(diǎn)擊效果,在自己閱讀源碼之前,也并沒有過更多留心過在這些表單控件的動(dòng)畫效果是如何實(shí)現(xiàn)的,甚至可能有時(shí)都沒注意到這些動(dòng)畫效果。下面先一起來看以下具體的效果(留意邊框以外,一閃一閃的波浪動(dòng)畫效果):

Button組件

Radio組件

Switch組件

???????看完UI效果之后我們大概已經(jīng)知道是什么了,再看代碼部分,由于代碼書寫順序與閱讀順序并不一致,為了方便理解,我們?cè)诜治鲈创a的過程中,會(huì)調(diào)整代碼解釋的順序

源碼分析
// 一個(gè)新的依賴,暫時(shí)不知道是什么,依據(jù)名字推測(cè)與動(dòng)畫效果有關(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);
  }
    
  // 在組件卸載時(shí),清除掉事件監(jiān)聽與定時(shí)器,避免內(nèi)存泄漏
  componentWillUnmount() {
    if (this.instance) {
      this.instance.cancel();
    }
    if (this.clickWaveTimeoutId) {
      clearTimeout(this.clickWaveTimeoutId);
    }
  }  

  // 根據(jù)名字推測(cè): 為DOM節(jié)點(diǎn)綁定動(dòng)畫效果,進(jìn)入函數(shù)內(nèi)部查看
  bindAnimationEvent = (node: HTMLElement) => {
   //... some code 

    const onClick = (e: MouseEvent) => {
      //... some code

      // 無論是否正在執(zhí)行動(dòng)畫,先清除掉動(dòng)畫效果(至于怎么清除,先不關(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,被用作儲(chǔ)存一個(gè)定時(shí)器
      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ù)封裝在一個(gè)對(duì)象中并作為返回值,看著這里應(yīng)該想起之前定義的私有變量instance,
    // 回顧DidMount生命周期函數(shù),你會(huì)發(fā)現(xiàn)這個(gè)返回的對(duì)象將會(huì)被儲(chǔ)存在instance中
    return {
      cancel: () => {
        node.removeEventListener("click", onClick, true);
      },
    };
  }

  //未完待續(xù)

我們通過觀察上方bindAnimationEvent方法,其主要做了三件事,調(diào)用了兩個(gè)外部函數(shù)this.resetEffectthis.onClick
1、過濾不執(zhí)行的條件(代碼省略掉了,非主干邏輯)
2、聲明onClick函數(shù),并作為node的點(diǎn)擊事件觸發(fā)時(shí)要執(zhí)行的函數(shù)
3、返回一個(gè)儲(chǔ)存了取消監(jiān)聽click事件方法的對(duì)象

個(gè)人認(rèn)為bindAnimationEvent方法,做了太多的事情,而ComponentDidMount做的事情太少(單一原則)
往下方,繼續(xù)查看 this.resetEffectthis.onClick 分別是做什么的,以及如何實(shí)現(xiàn)的

  // 這個(gè)函數(shù)是實(shí)現(xiàn)動(dòng)畫效果的核心,其主要有三個(gè)行為:1、創(chuàng)建內(nèi)聯(lián)style標(biāo)簽, 2、插入css字符串 3、并將其插入到document中
  // 我們知道css也是可以控制DOM變化的,比如偽類元素:after :before  這里正是通過:after來實(shí)現(xiàn)效果的
  onClick = (node: HTMLElement, waveColor: string) => {
    //... some code 1
    const { insertExtraNode } = this.props;

    /* 創(chuàng)建了一個(gè)div元素extraNode,裝飾該div,在inserExtracNode= true時(shí),將extraNode作為node的子元素 */
    /* 創(chuàng)建一個(gè)div元素,并緩存中私有變量extraNode中 */
    this.extraNode = document.createElement("div");
    
    /* 這里用let 更合適 */
    const extraNode = this.extraNode;
    extraNode.className = "ant-click-animating-node";
    // 可能有人好奇這個(gè)extraNode是干嘛的?
    // 往之后的代碼中看的時(shí)候會(huì)發(fā)現(xiàn),在insertExtraNode為false時(shí),Wave通過插入偽類元素:after 來作為承載動(dòng)畫效果的DOM元素
    // 在insertExtraNode = true時(shí),會(huì)生成一個(gè)div替代:after偽類元素,猜測(cè)是某些this.props.children可能自帶:after,所以
    // 使用div元素來替代:after避免沖突,在這里我們只需要知道它是作為承載動(dòng)畫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)建了一個(gè)內(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時(shí),將extraNode插入到node子元素中 */
    if (insertExtraNode) {
      node.appendChild(extraNode);
    }
    
    /* 為元素增加動(dòng)畫效果 */
    TransitionEvents.addEndEventListener(node, this.onTransitionEnd);
  }

  /**
   * 重置效果
   * 顧名思義:這個(gè)函數(shù)通過三個(gè)行為,致力于一件事情,取消動(dòng)畫效果
   * 1、刪除node的attribute屬性 2、node的子元素 3、刪除對(duì)應(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中刪除一個(gè)子節(jié)點(diǎn)。返回刪除的節(jié)點(diǎn)。
      node.removeChild(this.extraNode);
    }
    TransitionEvents.removeEndEventListener(node, this.onTransitionEnd);
  }

  // 刪除內(nèi)聯(lián)style標(biāo)簽
  removeExtraStyleNode() {
    if (styleForPesudo) {
      styleForPesudo.innerHTML = "";
    }
  }
      
  // 在每次動(dòng)畫執(zhí)行結(jié)束后,清除掉狀態(tài),完成一個(gè)生命周期
  onTransitionEnd = (e: AnimationEvent) => {
    // todo
    if (!e || e.animationName !== "fadeEffect") {
      return;
    }

    this.resetEffect(e.target as HTMLElement);
  }

}
組件邏輯:

我們回過頭來看第一部分的代碼,組件邏輯體現(xiàn)在componentDidMountcomponentWillUnMount
1、在componentDidMount中為this.props.childrenclick事件綁定動(dòng)畫執(zhí)行函數(shù)this.onClick,
2、在componentWillUnMount中清除與動(dòng)畫相關(guān)的狀態(tài)避免內(nèi)存泄漏。

組件運(yùn)行邏輯:

此時(shí),Wave組件的代碼與邏輯已經(jīng)全部分析完了,整個(gè)Wave組件的運(yùn)行邏輯可以通過下方這張圖來概括

本篇完~

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/102079.html

相關(guān)文章

  • Ant design的Notification源碼分析

    摘要:通過將實(shí)例傳入回調(diào)函數(shù)。添加再回過頭來看回調(diào)函數(shù)的內(nèi)容。其中的作用是一次調(diào)用傳入的各函數(shù),其中方法是移除中相應(yīng)的節(jié)點(diǎn),是傳入的關(guān)閉標(biāo)簽后的回調(diào)函數(shù)。 notification簡(jiǎn)介 showImg(https://segmentfault.com/img/remote/1460000014117558?w=483&h=135); notification就是通知提醒框,在系統(tǒng)四個(gè)角顯示通...

    SimpleTriangle 評(píng)論0 收藏0
  • Ant-Design-組件-——-Form表單(一)

    摘要:擅長(zhǎng)網(wǎng)站建設(shè)微信公眾號(hào)開發(fā)微信小程序開發(fā)小游戲制作企業(yè)微信制作建設(shè),專注于前端框架服務(wù)端渲染技術(shù)交互設(shè)計(jì)圖像繪制數(shù)據(jù)分析等研究。 Ant Design of React @3.10.9 拉取項(xiàng)目 luwei.web.study-ant-design-pro, 切換至 query 分支,可看到 Form 表單實(shí)現(xiàn)效果 實(shí)現(xiàn)一個(gè)查詢表單 showImg(https://segmentfau...

    trilever 評(píng)論0 收藏0
  • 前端最實(shí)用書簽(持續(xù)更新)

    摘要:前言一直混跡社區(qū)突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點(diǎn)混亂所以將前端主流技術(shù)做了一個(gè)書簽整理不求最多最全但求最實(shí)用。 前言 一直混跡社區(qū),突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點(diǎn)混亂; 所以將前端主流技術(shù)做了一個(gè)書簽整理,不求最多最全,但求最實(shí)用。 書簽源碼 書簽導(dǎo)入瀏覽器效果截圖showImg(https://segmentfault.com/img/bVbg41b?w=107...

    sshe 評(píng)論0 收藏0
  • TypeScript 、React、 Redux和Ant-Design的最佳實(shí)踐

    摘要:使用官方的的另外一種版本和一起使用自動(dòng)配置了一個(gè)項(xiàng)目支持。需要的依賴都在文件中。帶靜態(tài)類型檢驗(yàn),現(xiàn)在的第三方包基本上源碼都是,方便查看調(diào)試。大型項(xiàng)目首選和結(jié)合,代碼調(diào)試維護(hù)起來極其方便。 showImg(https://segmentfault.com/img/bVbrTKz?w=1400&h=930); 阿特伍德定律,指的是any application that can be wr...

    wangbinke 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<