blog
blog copied to clipboard
命令式调用你的 React web 组件
大多数时候,是这样使用 React 组件的:
通过显示地修改传递给组件的 props
来改变组件的状态(显隐、颜色、内容等),这在大多数时候非常好用,并且这就是 React 的设计哲学,这属于声明式调用,但考虑一下我们经常用到的弹框组件(toast、modal、loading),因为弹框组件会被经常调用,并且可能同时存在多个实例,这样就需要维护多个props的状态,同时还需要手动修改父组件的 state 来控制显隐,这是非常繁琐的。
类似于 antd 的message 的使用方式 message.info('This is a normal message')
,antd 称其为全局提示组件。
这种调用方式就是命令式调用,这种调用方式非常类似于以往 jQuery 时代的js库,好处在于不再需要不断地维护 组件 的状态,这对于 toast
、modal
、loading
来说非常有用。
其实设计这样一个组件并不难,其核心在于主动调用 ReactDOM.render
方法,将组件渲染上去,以设计一个 toast info
组件为例:
首先编写普通的 react
组件:
import React from 'react'
import ReactDOM from 'react-dom'
export interface InfoProps {
/**
* 提示消息
*/
msg: string
/**
* 图标类型,none,info,fail,success
* 默认为 none
*/
icon?: string
}
export default class Info extends React.Component<InfoProps, any> {
public defaultProps: InfoProps = {
msg: '',
icon: 'none'
}
render() :React.ReactNode{
const { icon, msg } = this.props
const showIcon = icon !== 'none'
const iconClass = `icon ${icon !== 'info' ? 'icon_' + icon : ''}`
return (
<div className="mod_alert_v2 show fixed">
{showIcon ? <i className={iconClass} /> : null}
<p>{msg}</p>
</div>
)
}
}
暴露一个普通方法,来手动挂载到页面上去
import React from 'react'
import ReactDOM from 'react-dom'
import Info, { InfoProps } from './Info'
export default function info(
opts: InfoProps & {
/**
* 计时消失毫秒数,默认 2000
*/
delay?: number
/**
* 是否显示蒙层
* 默认不显示
*/
showcoverdiv?: boolean
} = {
msg: ''
}
) {
const options = Object.assign(
{
msg: '',
delay: 2000,
icon: 'none',
showcoverdiv: false
},
opts
)
const div = document.createElement('div')
document.body.appendChild(div)
ReactDOM.render(<Info msg={options.msg} icon={options.icon} />, div)
setTimeout(() => {
ReactDOM.unmountComponentAtNode(div)
document.body.removeChild(div)
}, options.delay)
}
其核心就是通过 ReactDOM.render
来挂载上去的,通过 ReactDOM.unmountComponentAtNode
来卸载组件的。
简单的调用方式如下:
通过这种方式,可以很快地封装好你的 React 命令式组件,以个人经验而言,对于 web 常用的 toast
、modal
、loading
这三种组件应该是封装为这种组件会更加方便使用的。