1. portal
portal提供了一个最好的在父组件包含的DOM结构层级外的DOM节点渲染组件的方法,比如遮罩层。
举个例子,现在有一个父div里包着左div和右div,希望点击右div中的按钮能实现把两个div都遮罩起来,如果是常规创建右div会因为父组件的DOM元素有着overflow:hidden或者z-index等样式不那么好实现,因此可以采用portal的创建方法:
可以看到return了一个createProtal包装起来的div,第二个参数设置为document.body,意为此组件创建的容器。
export default class Dialog extends Component {
render() {
return createPortal(
<div style={{ width: '100%', height: '100%', position: 'fixed', left: 0, top: 0, background: 'rgba(0,0,0,0.7)', zIndex: "9999999" }}>
<button onClick={this.props.onCloseTheLayer}>close</button>
</div>,
document.body
)
}
}
这是父组件
export default class App extends Component {
state = {
isShow: false
}
render() {
return (
<div className="box">
<div className="left"></div>
<div className="right">
<button onClick={() => {
this.setState({
isShow: true
})
}}>ajax</button>
{
this.state.isShow && <Dialog onCloseTheLayer={() =>{
this.setState({
isShow: false
})
}}></Dialog>
}
</div>
</div>
)
}
}
虽然通过portal渲染的元素在父组件的盒子之外,但是渲染的dom节点仍在React的元素树上,在那个dom元素上的点击事件仍然能在dom树中监听到。
具体原因可以看react事件的那篇博客,react所有事件统一挂载在根节点上管理
2. 懒加载
通过React.lazy函数实现动态引入组件,也即懒加载。
当程序越来越大,代码量越来越多。一个页面上堆积了很多功能,也许有些功能很可能都用不到,但是一样下载加载到页面上,所以这些加载可以被优化。
该函数原理是当Webpack解析到该语法时,它会自动地开始进行代码分割(Code Splitting),分割成一个文件,当使用到这个文件的时候会这段代码才会被异步加载。
在React.lazy和常用的三方包react-loadable,都是使用了这个原理,然后配合webpack进行代码打包拆分达到异步加载,这样首屏渲染的速度将大大的提高。
由于React.lazy不支持服务端渲染,所以这时候react-loadable就是不错的选择。
具体用法:
- 导入组件时使用React.lazy()
- 通过Suspense包装起需要懒加载的组件,并且在fallback参数中提供加载时要展示的内容/组件
const Nowplaying = React.lazy(() => import('./components/Nowplaying'))
const Comingsoon = React.lazy(() => import('./components/Comingsoon'))
export default class App extends Component {
state = {
type: 1
}
render() {
return (
<div>
<button onClick={() => {
this.setState({
type: 1
})
}}>正在热映</button>
<button onClick={() => {
this.setState({
type: 2
})
}}>即将上映</button>
<Suspense fallback={<div>正在加载中....</div>}>
{
this.state.type === 1 ?
<Nowplaying></Nowplaying>
:
<Comingsoon></Comingsoon>
}
</Suspense>
</div>
)
}
}