React组件的封装

按钮

type ButtonType = 'default' | 'primary'

interface Props {
  type?: ButtonType
  onClick?: () => void
}

export default class Button extends React.Component<Props> {

  static defaultProps = {
    type:'default'
  }

  render() {
    const {type,onClick} = this.props
    let btnclassname = `button button-${type}`
    return <button className = {btnclassname} onClick={onClick}>
      {this.props.children}
    </button>
  }
  
}

使用

<Button>默认按钮</Button>
<Button type="primary">主按钮</Button>
<Button type="primary" onClick={this.showModal}>

模态框

  1. 首先定义一个模态框组件的类,关于模态框内部的样式布局我们在这里面写
  2. 在父组件中定义控制模态框状态的visible: boolean,以及我们模态框中的标题内容等,在父组件中引入模态框组件时把模态框中需要的内容传入
  3. 在父组件中定义控制模态框显示状态的方法,如打开模态框,关闭模态框等,将关闭模态框的函数也传入子组件,在子组件中取消和关闭等组件的点击事件绑定我们传入的关闭模态框函数,实现模态框的打开和关闭
  4. 实现模态框打开关闭的过渡动画效果

全部CSS代码



/* Button组件样式 */
.button {
  line-height: 1.5715;
  margin: 0 5px;
  position: relative;
  display: inline-block;
  font-weight: 400;
  white-space: nowrap;
  text-align: center;
  border: 1px solid transparent;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  height: 32px;
  padding: 4px 15px;
  font-size: 14px;
  border-radius: 2px;
}

/* 按钮默认样式 */
.button-default {
  color: #000000d9;
  border-color: #d9d9d9;
  background: #fff;
}

.button-default:hover {
  color: #40a9ff;
  border-color: #40a9ff;
}

/* 按钮主样式 */
.button-primary {
  color: #fff;
  border-color: #40a9ff;
  background: #40a9ff;
}

.button-primary:hover {
  color: #fff;
  border-color: #69c0ff;
  background: #69c0ff;
}

/* Modal组件样式 */
.modal {
  visibility: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
}
.modal-mask {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 100;
  transition: all 0.4s ease-in-out;
  opacity: 0;
}
.modal-box {
  box-sizing: border-box;
  position: relative;
  z-index: 101;
  width: 520px;
  background: #fff;
  border-radius: 5px;
  transition: all 0.3s ease-in-out;
  opacity: 0;
  transform: scale(0.7);
}
.modal-visible {
  visibility: visible;
}
.modal-visible .modal-mask {
  opacity: 1;
}
.modal-visible .modal-box {
  opacity: 1;
  transform: scale(1);
}
.modal-head {
  border-bottom: 1px solid #f0f0f0;
  padding: 16px 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  color: #333;
  font-size: 16px;
  font-weight: 500;
}
.modal-close {
  cursor: pointer;
  opacity: 0.7;
}
.modal-close:hover {
  opacity: 1;
}
.modal-body {
  padding: 24px;
  font-size: 14px;
  color: #333;
  line-height: 1.6em;
}
.modal-footer {
  border-top: 1px solid #f0f0f0;
  padding: 10px 16px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
}
.modal-footer > * {
  margin-left: 10px;
}


模态框组件代码

interface Props {
  visible: boolean
  title: string
  footer: React.ReactNode
  onClose: () => void
}

export default class Modal extends React.Component<Props> {

  render() {
    let closeBtn = (
      <svg
        viewBox="64 64 896 896"
        focusable="false"
        data-icon="close"
        width="1em"
        height="1em"
        fill="currentColor"
        aria-hidden="true"
        className="modal-close"
        onClick={this.props.onClose}
      >
        <path d="M563.8 512l262.5-312.9c4.4-5.2.7-13.1-6.1-13.1h-79.8c-4.7 0-9.2 2.1-12.3 5.7L511.6 449.8 295.1 191.7c-3-3.6-7.5-5.7-12.3-5.7H203c-6.8 0-10.5 7.9-6.1 13.1L459.4 512 196.9 824.9A7.95 7.95 0 00203 838h79.8c4.7 0 9.2-2.1 12.3-5.7l216.5-258.1 216.5 258.1c3 3.6 7.5 5.7 12.3 5.7h79.8c6.8 0 10.5-7.9 6.1-13.1L563.8 512z"></path>
      </svg>
    )

    return (
      <div className={this.props.visible ? 'modal modal-visible' : 'modal'}>
        <div className="modal-mask" onClick={this.props.onClose} />
        <div className="modal-box">
          <div className="modal-head">
            <span>{this.props.title}</span>
            {closeBtn}
          </div>
          <div className="modal-body">{this.props.children}</div>
          <div className="modal-footer">{this.props.footer}</div>
        </div>
      </div>
    )
  }
}

主界面

import Button from './components/Button.js'
import Modal from './components/Modal.js'

interface State {
  visible: boolean
}

class App extends React.Component<any, State> {
  state: State = {
    visible: false
  }

  showModal = () => {
    console.log(111111111);

    this.setState({
      visible: true
    })
  }

  closeModal = () => {
    this.setState({
      visible: false
    })
  }

  render() {
    return (
      <React.Fragment>
        <Button>默认按钮</Button>
        <Button type="primary">主按钮</Button>
        <Button type="primary" onClick={this.showModal}>
          打开对话框
        </Button>
        <Modal
            visible={this.state.visible}
            title="窗口标题"
            // 实现关闭窗口的逻辑
            onClose={this.closeModal}
            footer={[
              // 实现关闭窗口的逻辑
              <Button key="cancel" onClick={this.closeModal}>取消</Button>,
              // 实现关闭窗口的逻辑
              <Button key="ok" onClick={this.closeModal} type="primary">确认</Button>
            ]}
          >
            <p>Some contents...</p>
            <p>Some contents...</p>
            <p>Some contents...</p>
          </Modal>

      </React.Fragment>
    )
  }
}

ReactDOM.render(<App />, document.getElementById('app'))

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值