動手實現react Modal組件

來源:互聯網
上載者:User
Modal組件

長話不多說,接下來讓我們來動手實現一個react Modal組件。

我們先來看一下實際效果

Modal的布局

首先,讓我們先思考下一個Modal組件的布局是怎麼樣的。

我們先拿一個基本的Modal範例來分析下。

如所示,一個Modal組件可以分為mask、header、body和footer四部分,mask就不用說了,header主要是顯示title和關閉按鈕,body則是使用者自己傳的內容,footer主要是按鈕控制項。

Modal組件的參數(props)

我們確定了Modal組件的布局之後,我們來思考一下Modal組件可支援傳遞的參數。

作為一個Modal組件,總要有標題(title)吧?要有使用者自訂傳入的內容(children),還有一個確定按鈕文案(okText)和一個取消按鈕文案(cancelText)吧,並且允許使用者傳入點擊確定按鈕的回呼函數(onOk)和點擊取消按鈕的回呼函數(onCancel)。也需要有一個控制Modal是否顯示的標誌吧(visible)。所以,大體上有以下7個變數。

Modal的樣式

首先,根據Modal組件的布局和參數,我們可以確定react Modal的render函數如下:

我們都知道,Modal會覆蓋在其他元素上面,並且主要分為兩部分,一部分為mask陰影部分,一部分為主體內容,而且主體部分會覆蓋在陰影部分上面。讓我們一步步來實現這個效果。

  1. 實現mask效果

    .modal-mask {  // 讓mask鋪滿整屏  position: fixed;  top: 0;  left: 0;  right: 0;  bottom: 0;  background: black;  opacity: 0.6;  // 讓mask覆蓋在其他元素上面  z-index: 1000;}
  2. 實現主體內容的樣式,讓其覆蓋在其他元素(包括mask)上面,每一部分的作用可以看注釋

    .modal-container {  // 讓Modal的主體內容全域置中,通過position: fix以及top和left的50%讓主體內容的左上方置中,再通過transform:translate(-50%, -50%)來讓主體內容正確置中。  position: fixed;  top: 50%;  left: 50%;  transform: translate(-50%, -50%);  background: white;  min-width: 500px;  border-radius: 4px;  // 設定主體內容的z-index高於mask的,從而可以覆蓋mask  z-index: 1001;}
  3. 接下來是body、footer和header樣式的實現,這個就直接貼代碼了。

    .modal-title {  padding: 30px;  color: black;  font-size: 20px;  border-bottom: 1px solid #e8e8e8;}.modal-body {  padding: 30px;  font-size: 14px;  border-bottom: 1px solid #e8e8e8;}.modal-footer {  text-align: center;  padding: 30px;  display: flex;}.modal-footer .btn {  flex: 1;  height: 32px;  text-align: center;}.modal-footer .modal-cancel-btn {  background: white;  margin-right: 30px;  border-color: #d9d9d9;  border-radius: 4px;}.modal-footer .modal-confirm-btn {  background: #1890ff;  color: white; }
Modal的互動邏輯實現

實際上Modal的互動是很簡單的,一般的調用方式如下:

由外部傳遞自訂的body內容以及一些自訂的屬性(比如title,點擊按鈕的回調還有Modal的標題)

  1. 我們先定義Modal組件裡的props

  2. 設定一些預設的props,當使用者未傳入參數的時候,則使用預設的props

  3. 實現render函數,根據使用者傳入的參數以及預設參數來渲染Modal節點,如果使用者傳入的visible屬性為false(Modal不可見),則返回null,否則,返回Modal節點。

這樣,一個簡單的react Modal組件就完成了,上面的代碼可以在github.com/chenjigeng/empty 查看,並且可以直接看到一個demo例子。

如下:

最後再貼一下完整的Modal組件代碼

// Modal.tsximport * as React from 'react';import './Modal.css';interface IModalProps {  children: React.ReactChild | React.ReactChildren |  React.ReactElement<any>[],  title?: React.ReactChild,  visible: boolean,  onOk?: () => void,  onCancel?: () => void,  okText?: string,  cancelText?: string,} export default class Modal extends React.Component<IModalProps> {  public static defaultProps = {    cancelText: '取消',    okText: '確定',    visible: false,  }    public render() {    const { title, visible, okText, cancelText, children, onOk, onCancel } = this.props;    if (!visible)  {      return null;    };    return (      <div>        <div className="modal-mask" onClick={onCancel}/>        <div className="modal-container">          <div className="modal-header">            <div className="modal-title">{title}</div>          </div>          <div className="modal-body">            {children}          </div>          <div className="modal-footer">            <button className="modal-cancel-btn btn" onClick={onCancel}>{cancelText}</button>            <button className="modal-confirm-btn btn" onClick={onOk}>{okText}</button>          </div>        </div>      </div>    )  }}
// Moda.css.modal-mask {  position: fixed;  top: 0;  left: 0;  right: 0;  bottom: 0;  background: black;  opacity: 0.6;  z-index: 1000;}.modal-container {  position: fixed;  top: 50%;  left: 50%;  transform: translate(-50%, -50%);  background: white;  min-width: 500px;  border-radius: 4px;  z-index: 1001;}.modal-title {  padding: 30px;  color: black;  font-size: 20px;  border-bottom: 1px solid #e8e8e8;}.modal-body {  padding: 30px;  font-size: 14px;  border-bottom: 1px solid #e8e8e8;}.modal-footer {  text-align: center;  padding: 30px;  display: flex;}.modal-footer .btn {  flex: 1;  height: 32px;  text-align: center;}.modal-footer .modal-cancel-btn {  background: white;  margin-right: 30px;  border-color: #d9d9d9;  border-radius: 4px;}.modal-footer .modal-confirm-btn {  background: #1890ff;  color: white; }
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.