成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Ant design的Notification源碼分析

SimpleTriangle / 2874人閱讀

摘要:通過將實例傳入回調(diào)函數(shù)。添加再回過頭來看回調(diào)函數(shù)的內(nèi)容。其中的作用是一次調(diào)用傳入的各函數(shù),其中方法是移除中相應(yīng)的節(jié)點,是傳入的關(guān)閉標(biāo)簽后的回調(diào)函數(shù)。

notification簡介

notification就是通知提醒框,在系統(tǒng)四個角顯示通知提醒信息。經(jīng)常用于以下情況:

較為復(fù)雜的通知內(nèi)容。

帶有交互的通知,給出用戶下一步的行動點。

系統(tǒng)主動推送。

先來看一下notification的API。

API

notification.success(config)

notification.error(config)

notification.info(config)

notification.warning(config)

notification.warn(config)

notification.close(key: String)

notification.destroy()

可以看到,notification的API在antd的組件中可以說是非常另類的,看著是不是有點眼熟,很像經(jīng)常使用的Console的API,調(diào)用起來十分簡單。

console.log()

console.error()

console.info()

console.warn()

config的配置也比較簡單,主要是標(biāo)題,內(nèi)容,關(guān)閉時的延時和回調(diào)等。詳見ANTD的官網(wǎng)。

notification的結(jié)構(gòu)

在分析代碼之前,我們先來看下notification的結(jié)構(gòu),通知組件主要分為三層,由高到低是

NotificationApi => Notification => n*Notice。

NotificationApi

NotificationApi是一個封裝的接口,提供統(tǒng)一調(diào)用的API,如info(),warn()等。

Notification

Notification是一個Notice容器,就是用來容納Notice列表的父組件,提供了添加,刪除等操作Notice的方法。

Notice

Notice就是我們所看到的通知標(biāo)簽了。

源碼分析

先從入口index.js入手,因為這是一個notification的API封裝,不是一個組件,所以沒有render方法。

//.......省略部分代碼........

const api: any = {
  open: notice,//入口
  close(key: string) {
    Object.keys(notificationInstance)
      .forEach(cacheKey => notificationInstance[cacheKey].removeNotice(key));
  },
  config: setNotificationConfig,
  destroy() {
    Object.keys(notificationInstance).forEach(cacheKey => {
      notificationInstance[cacheKey].destroy();
      delete notificationInstance[cacheKey];
    });
  },
};

//.......省略部分代碼........

["success", "info", "warning", "error"].forEach((type) => {
  api[type] = (args: ArgsProps) => api.open({
    ...args,
    type,
  });
});

api.warn = api.warning;
export interface NotificationApi {
  success(args: ArgsProps): void;
  error(args: ArgsProps): void;
  info(args: ArgsProps): void;
  warn(args: ArgsProps): void;
  warning(args: ArgsProps): void;
  open(args: ArgsProps): void;
  close(key: string): void;
  config(options: ConfigProps): void;
  destroy(): void;
}
export default api as NotificationApi;

接口比較清晰,可以看出API提供的不同的方法實際是通過一個類似工廠方法的open函數(shù)實現(xiàn)的,open函數(shù)的具體實現(xiàn)是notice,那么看下這個notice函數(shù)。

function notice(args: ArgsProps) {
  const outerPrefixCls = args.prefixCls || "ant-notification";
  const prefixCls = `${outerPrefixCls}-notice`;
  const duration = args.duration === undefined ? defaultDuration : args.duration;

//生成icon組件
  let iconNode: React.ReactNode = null;
  if (args.icon) {
    iconNode = (
      
        {args.icon}
      
    );
  } else if (args.type) {
    const iconType = typeToIcon[args.type];
    iconNode = (
      
    );
  }

  const autoMarginTag = (!args.description && iconNode)
    ? 
    : null;

  getNotificationInstance(outerPrefixCls, args.placement || defaultPlacement, (notification: any) => {
    notification.notice({
      content: (
        
{iconNode}
{autoMarginTag} {args.message}
{args.description}
{args.btn ? {args.btn} : null}
), duration, closable: true, onClose: args.onClose, key: args.key, style: args.style || {}, className: args.className, }); }); }

這段代碼主要的部分就是調(diào)用了getNotificationInstance函數(shù),看名字應(yīng)該是得到Notification的實例,命名方式是典型的單例模式,作為列表的容器組件,使用單例模式不僅節(jié)省了內(nèi)存空間,而且單例延遲執(zhí)行的特性也保證了在沒有通知的情況下不會生成notification組件,提升了頁面的性能。

function getNotificationInstance(prefixCls: string, placement: NotificationPlacement, callback: (n: any) => void)

查看定義,第一個參數(shù)是css前綴,第二個參數(shù)是notification的彈出位置,分為topLeft topRight bottomLeft bottomRight,第三個參數(shù)是一個回調(diào),回調(diào)的參數(shù)是notification實例,可以看到,在回調(diào)中調(diào)用了notification的notice方法,notice方法的參數(shù)是一個對象,content看名字應(yīng)該是通知標(biāo)簽的內(nèi)容,其他的參數(shù)也是調(diào)用notification中傳入的config參數(shù)。
接下來看下getNotificationInstance的實現(xiàn)

function getNotificationInstance(prefixCls: string, placement: NotificationPlacement, callback: (n: any) => void) {
  const cacheKey = `${prefixCls}-${placement}`;
  if (notificationInstance[cacheKey]) {
    callback(notificationInstance[cacheKey]);
    return;
  }

  //---實例化Notification組件
  (Notification as any).newInstance({
    prefixCls,
    className: `${prefixCls}-${placement}`,
    style: getPlacementStyle(placement),
    getContainer: defaultGetContainer,
  }, (notification: any) => {
    notificationInstance[cacheKey] = notification;
    callback(notification);
  });
}

代碼很簡短,可以看到確實是使用了單例模式,因為存在4個彈出位置,所以將每個位置的notification實例存放在notificationInstance[cacheKey]數(shù)組里,cacheKey是css前綴和彈出位置的組合,用以區(qū)分每個實例。接下來進(jìn)入newInstance方法來看下是怎么使用單例模式生成notification實例的。

實例化Notification
Notification.newInstance = function newNotificationInstance(properties, callback) {
  const { getContainer, ...props } = properties || {};
  const div = document.createElement("div");
  if (getContainer) {
    const root = getContainer();
    root.appendChild(div);
  } else {
    document.body.appendChild(div);
  }
  let called = false;
  function ref(notification) {
    if (called) {
      return;
    }
    called = true;
    callback({
      notice(noticeProps) {
        notification.add(noticeProps);
      },
      removeNotice(key) {
        notification.remove(key);
      },
      component: notification,
      destroy() {
        ReactDOM.unmountComponentAtNode(div);
        div.parentNode.removeChild(div);
      },
    });
  }
  ReactDOM.render(, div);
};

主要完成了兩件事

通過ReactDOM.render將Notification組件渲染到頁面上,可以選擇渲染到傳入的container或者body中。

通過ref將notification實例傳入callback回調(diào)函數(shù)。

可以看到傳入callback的參數(shù)對notification又做了一層封裝,目的是為了封裝destroy函數(shù),其中

+ notice():添加一個notice組件到notification
+ removeNotice():刪除指定notice組件。
+ destroy():銷毀notification組件。
添加Notice

再回過頭來看回調(diào)函數(shù)的內(nèi)容。

 getNotificationInstance(outerPrefixCls, args.placement || defaultPlacement, (notification: any) => {
    notification.notice({
      content: (
        
{iconNode}
{autoMarginTag} {args.message}
{args.description}
{args.btn ? {args.btn} : null}
), duration, closable: true, onClose: args.onClose, key: args.key, style: args.style || {}, className: args.className, }); });

調(diào)用了notification的notice方法,由前面的代碼可知notice其實是調(diào)用了Notification組件的add方法,記下來看下add方法是怎樣將標(biāo)簽添加進(jìn)Notification的。

//省略部分代碼

 state = {
  notices: [],
};

//省略部分代碼

  add = (notice) => {
  const key = notice.key = notice.key || getUuid();
  this.setState(previousState => {
    const notices = previousState.notices;
    if (!notices.filter(v => v.key === key).length) {
      return {
        notices: notices.concat(notice),
      };
    }
  });
}

Notification將要顯示的通知列表存在state的notices中,同通過add函數(shù)動態(tài)添加,key是該notice的唯一標(biāo)識,通過filter將已存在的標(biāo)簽過濾掉??梢韵胍姡琋otification就是將state中的notices通過map渲染出要顯示的標(biāo)簽列表,直接進(jìn)入Notification組件的render方法。

  render() {
  const props = this.props;
  const noticeNodes = this.state.notices.map((notice) => {
    const onClose = createChainedFunction(this.remove.bind(this, notice.key), notice.onClose);
    return (
      {notice.content}
    );
  });
  const className = {
    [props.prefixCls]: 1,
    [props.className]: !!props.className,
  };
  return (
    
{noticeNodes}
); } }

根據(jù)state的notices生成Notice組件列表noticeNodes,然后將noticeNodes插入到一個Animate的動畫組件中。其中createChainedFunction的作用是一次調(diào)用傳入的各函數(shù),其中remove方法是移除state中相應(yīng)的節(jié)點,onClose是傳入的關(guān)閉標(biāo)簽后的回調(diào)函數(shù)。
看到這里Notification的結(jié)構(gòu)已經(jīng)比較清晰了,最后再來看下Notice組件的實現(xiàn)。

export default class Notice extends Component {
  static propTypes = {
    duration: PropTypes.number,
    onClose: PropTypes.func,
    children: PropTypes.any,
  };

  static defaultProps = {
    onEnd() {
    },
    onClose() {
    },
    duration: 1.5,
    style: {
      right: "50%",
    },
  };

  componentDidMount() {
    this.startCloseTimer();
  }

  componentWillUnmount() {
    this.clearCloseTimer();
  }

  close = () => {
    this.clearCloseTimer();
    this.props.onClose();
  }

  startCloseTimer = () => {
    if (this.props.duration) {
      this.closeTimer = setTimeout(() => {
        this.close();
      }, this.props.duration * 1000);
    }
  }

  clearCloseTimer = () => {
    if (this.closeTimer) {
      clearTimeout(this.closeTimer);
      this.closeTimer = null;
    }
  }

  render() {
    const props = this.props;
    const componentClass = `${props.prefixCls}-notice`;
    const className = {
      [`${componentClass}`]: 1,
      [`${componentClass}-closable`]: props.closable,
      [props.className]: !!props.className,
    };
    return (
      
{props.children}
{props.closable ? : null }
); } }

這個組件比較簡單,主要是實現(xiàn)標(biāo)簽顯示一段時間后自動消失,通過setTimeout設(shè)置一段時間后調(diào)用close方法,也就是上一段代碼中實現(xiàn)的移除state中的相應(yīng)節(jié)點以及調(diào)用相應(yīng)的回調(diào)函數(shù)。

總結(jié)

看到這里antd的通知組件的實現(xiàn)已經(jīng)比較清晰了,代碼并沒有特別復(fù)雜的部分,但是這種使用單例模式動態(tài)添加組件的設(shè)計十分值得借鑒,在實現(xiàn)類似通知組件或者需要動態(tài)添加的組件的時候可以參考這種設(shè)計模式,antd的Message組件也采用了同樣的設(shè)計。

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

轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/93885.html

相關(guān)文章

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

    摘要:返回刪除的節(jié)點。組件運行邏輯此時,組件的代碼與邏輯已經(jīng)全部分析完了,整個組件的運行邏輯可以通過下方這張圖來概括本篇完 Wave組件效果預(yù)覽 ???????在上一篇文章Button組件的源碼分析中遇到了一個Wave組件, Wave組件在Ant design中提供了通用的表單控件點擊效果,在自己閱讀源碼之前,也并沒有過更多留心過在這些表單控件的動畫效果是如何實現(xiàn)的,甚至可能有時都沒注意到這...

    luzhuqun 評論0 收藏0
  • Vue開發(fā)總結(jié) 及 一些最佳實踐 (已更新)

    摘要:基本開發(fā)環(huán)境創(chuàng)建的項目,作為代碼編寫工具插件推薦插件配置文章目錄項目目錄結(jié)構(gòu)介紹框架選擇處理請求二次封裝項目目錄結(jié)構(gòu)簡介業(yè)務(wù)相關(guān)靜態(tài)文件全局組件基礎(chǔ)樣式布局樣式及工具引入請求配置路由全局狀態(tài)管理工具文件入口文件主要配置文件頁面檢查配置測試 基本開發(fā)環(huán)境 vue-cli3 創(chuàng)建的項目,vscode 作為代碼編寫工具vscode插件推薦:vscode 插件配置 文章目錄 項目目錄結(jié)構(gòu)介紹...

    NotFound 評論0 收藏0
  • 用React實現(xiàn)一個最最最簡單TodoList

    摘要:初學(xué),擼一個熟悉熟悉基本語法,只有最簡單最簡單的功能。引入這個之后,我們可以直接使用一些簡單的組件,比如等,我們可以更加注重業(yè)務(wù)邏輯的實現(xiàn)。 初學(xué)React,擼一個TodoList熟悉熟悉基本語法,只有最簡單最簡單的功能。 showImg(https://segmentfault.com/img/remote/1460000010376536); 如上圖所示,是一個最簡單的TodoLi...

    Forest10 評論0 收藏0
  • Ant-Design-組件-——-Form表單(一)

    摘要:擅長網(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...

    trilever 評論0 收藏0

發(fā)表評論

0條評論

SimpleTriangle

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<