React对话框组件实现
当下前端届最火的技术之一莫过于React + Redux + webpack的技术结合。最近公司内部也正在转react,这周主要做了个React的modal组件,接下来谈下具体实现过程。
基本的HTML结构
虽然React基于虚拟DOM,但他的JSX语法还是离不开最基本的HTML。第一步要做的就是通过HTML&&CSS实现Dialog垂直水平居中框。HTML结构如下:
<div className="m-mask"></div>
<div className="m-dialog">
<div className="md-dialog">
<div className="md-dialog-title">
<h4>{title}</h4>
<span className="btn">
<i className="iconfont">×</i>
</span>
</div>
<div className="md-dialog-content">
{this.props.children}
</div>
<div className="md-dialog-foot">
<a href="#" className="btns">取消</a>
<a href="#" className="btns btns-blue">确定</a>
</div>
</div>
</div>
ps: JSX语法的className对应于HTML中的class,其次文中的iconfont图标被换成了×。
然后写下对应的CSS样式。此处主要说明一下主要的样式布局原理,细节略过。
Modal框的背景mask样式通过position:fixed + top/right/bottom/left:0 + height: 100%实现。
不定宽高的主体内容水平垂直居中的实现通过position:fixed + top/left: 50% + translate(-50%, -50%)实现。
React Modal Component
有了已经想好的布局样式,开始实现最基本的Modal组件。因为需要动态控制组件的显隐,所以组件的显隐在内部要通过state方便控制,而其他属性则通过props实现。modal.js代码如下:
import React, { Component, PropTypes } from 'react'
const defaultProps = {
show: false,
title: '',
zIndex: 1000,
onOk: () => {},
onCancel: () => {},
}
const propTypes = {
title: PropTypes.string,
zIndex: PropTypes.number,
onOk: PropTypes.func,
onCancel: PropTypes.func,
}
export default class Modal extends Component {
constructor(props) {
super(props)
this.state = {show: props.show}
}
render() {
return (
// JSX语法的HTML
);
}
}
Modal.defaultProps = defaultProps
Modal.propTypes = propTypes
不过显隐内部通过state控制,但父组件还是需要通过props传递初始默认值。而且来回调用同一个modal时,父组件是通过props中的show属性控制。内部的state还是第一次调用时传入的props值。这样无法导致及时控制显隐。此时react的componentWillReceiveProps()出场,完美解决这个bug。
俗话说bug是解不完的,虽然上面的组件勉强可以正常使用,但是用于样式通过绝对定位来做的,无形中导致了另外一个坑,如果Modal的父组件采用了相对或者绝对定位,即影响了Modal组件的定位,就会存在Modal出现在了某个div中,而不是理想的body中。bug复现如下:

unstable_renderSubtreeIntoContainer登场
为了保证我们的组件始终处于body中,采取了ReactDOM中的的这个不太正式的API。语法很简单:
ReactDOM.unstable_renderSubtreeIntoContainer(parent, component, dom)
parent一般是this,component是Modal,dom是div
代码实现如下:
export default class extends Component {
appendMaskIntoDoc() {
ReactDOM.unstable_renderSubtreeIntoContainer(
this,
<Modal {...this.props}>
{this.props.children}
</Modal>,
this.container
)
}
componentDidMount() {
this.container = document.createElement('div')
document.body.appendChild(this.container)
this.appendMaskIntoDoc()
}
componentDidUpdate() {
this.appendMaskIntoDoc()
}
componentWillUnmount() {
document.body.removeChild(this.container)
}
render() {
return null
}
}
API形式
此时,Modal组件已经成功做出来了。父组件可以成功调用,效果如下:

不过,偷偷see了下蚂蚁金服官网的Modal组件调用,还有一种API形式的调用。于是也简单实现了下。这里,简单说下实现思路吧。
Confirm function内部通过setState方法函数接受的参数传递给Modal的父组件dialog,onOk的promise异步回调则是在dialog内部通过处理之后再传递给Modal组件。
此处我是通过正则表达式检测new Promise,如果属于Promise,则给onOk绑定then,内部调用setState控制Modal的隐藏。不过在调用Confirm function之前,
dialog组件已经被render进ReactDOM中,render之前则需要dom节点,就需要能获取到document节点。然后手动创建空div节点添加到body中。
此处代码有点长,省略咯。
完整的代码已放到github上。https://github.com/qingguoing/react-modal
React对话框组件实现的更多相关文章
- 基于React.js网页版弹窗|react pc端自定义对话框组件RLayer
基于React.js实现PC桌面端自定义弹窗组件RLayer. 前几天有分享一个Vue网页版弹框组件,今天分享一个最新开发的React PC桌面端自定义对话框组件. RLayer 一款基于react. ...
- 移动web端的react.js组件化方案
背景: 随着互联网世界的兴起,web前端开发的方式越来越多,出现了很多种场景开发的前端架构体系,也对前端的要求日益增高,早已经不是靠一个JQuery.js来做前端页面的时代了,而今移动端变化最大,近 ...
- Griddle, griddle-react 一个REACT 表格组件
Griddle, griddle-react 一个REACT 表格组件: http://griddlegriddle.github.io/Griddle/index.html
- React Native组件之Text
React Native组件之Text相当于iOS中的UILabel. 其基本属性如下: /** * Sample React Native App * https://github.com/face ...
- React Native组件之Switch和Picker和Slide
React Native组件Switch类似于iOS中的UISwitch:组件Slide类似于iOS中UIslider,组件Picker类似于iOS的UIPickerView.他们的使用方法和相关属性 ...
- artDialog是一个基于javascript编写的对话框组件,它拥有精致的界面与友好的接口
artDialog是一个基于javascript编写的对话框组件,它拥有精致的界面与友好的接口 自适应内容 artDialog的特殊UI框架能够适应内容变化,甚至连外部程序动态插入的内容它仍然能自适应 ...
- reactjs入门到实战(七)---- React的组件的生命周期
React的组件的生命周期有三个状态分别是:挂载(生产组件示例化.准备挂载到页面.挂载到页面).更新(更新值.更新DOM).和卸载(卸载后). >>>其他 getInitia ...
- React Native 组件之TextInput
React Native 组件之TextInput类似于iOS中的UITextView或者UITextField,是作为一个文字输入的组件,下面的TextInput的用法和相关属性. /** * Sa ...
- [Python] wxPython 状态栏组件、消息对话框组件 学习总结(原创)
1.状态栏组件 1.基本介绍 上图: 红框框内的就是状态栏. 他可以分成若干个区块,比如上者分为了两个区块,并且比例是固定的,创建时可以指定 每个区块都能够显示 信息,一般通过 绑定事件 实时更新 各 ...
随机推荐
- Linux下添加硬盘,分区,格式化详解
2005-10-17 在我们添加硬盘前,首先要了解linux系统下对硬盘和分区的命名方法. 在Linux下对IDE的设备是以hd命名的,第一个ide设备是hda,第二个是hdb.依此类推 我们一般主板 ...
- [转]MySQL与MongoDB的操作对比
MySQL与MongoDB都是开源的常用数据库,但是MySQL是传统的关系型数据库,MongoDB则是非关系型数据库,也叫文档型数据库,是一种NoSQL的数据库.它们各有各的优点,关键是看用在什么地方 ...
- mingW与cygwin
转自:http://hi.baidu.com/ooxxer/item/d25dccc072846a50ac00ef7e# 首先MingW和cygwin都可以用来跨平台开发. MinGW是Minima ...
- 【转】ORATOP工具使用说明
文章转自:http://lintzyuan.blogspot.jp/2014/07/oratop.html ORATOP 前言:隨著PC Server的規格及速度愈來愈快,大多數的公司摒棄大型主機 ...
- ArcGIS Server注册地理数据库报machine:机器名[Oracle:(null)]错误的修改
环境介绍:本机安装了ArcGIS Server10.2,ArcGIS Desktop10.2,64位Oracle11g以及Oracle32位客户端.直连和服务连接都能成功. 问题:我要进行服务发布的时 ...
- LitePal + Gson + Volley的ORM框架尝试方案
为了紧跟技术潮流,目前的项目开始采用ORM的思想进行重新设计. 数据库采用轻量级ORM框架LitePal,Json解析采用Gson,网络框架采用Volley. 如果只是单纯的将这些第三方框架引进来,事 ...
- 一起Polyfill系列:让Date识别ISO 8601日期时间格式
一.什么是ISO 8601日期时间格式 ISO 8601是国际标准化组织制定的日期时间表示规范,全称是<数据存储和交换形式·信息交换·日期和时间的表示方法>. 示例: 1. 2014-12 ...
- 如何单独启动wamp 中自带的MySQL
前言:Wamp集成了Apache.MySQL和PHP环境.使用Wamp进行网站开发,是很多网站开发爱好者的选择.同时,其集成的MySQL服务,也常被用于MySQL的开发.这个时候我们只是想启动MySQ ...
- HDFS Append时packet的格式以及DataNode对block/checksum文件的处理
HDFS Append时packet的格式以及DataNode对block/checksum文件的处理 HDFS的Block一般比较大,默认64MB/128MB,客户端给DataNode发数据实际上是 ...
- asp.net mvc中包含webapi时,token失效产生302的解决方案
public void ConfigureAuth(IAppBuilder app) { app.UseCookieAuthentication(new CookieAuthenticationOpt ...