React16是Facebook在2017年9月发布的React最新版本。他是基于代号为“Fiber”的新架构实现,几乎对React的底层代码进行了重写,但是原本对外的api保持不变,所以基本可以无缝的迁移到React16,但是对于React16基于以前版本的React实现了许多比较新的特性。
一,React的render方法返回的新类型:支持两种类型数组(由React元素组成)和字符串
1,返回数组,如:
class ListComponent extends Component{
render(){
return[
<li key="A">A</li>,
<li key="B">B</li>
<li key="C">C</li>
]
}
}
2,返回字符串
class StringComponent extends Component{
render(){
return "I am a String"
}
}
组件的render方法渲染ListComponent和StringComponent;
export class App extends Component{
render(){
return[
<ul>
<listComponent/>
</ul>,
<StringComponent/>
]
}
}
二,错误处理
React16之前组件如果在运行期间出错,就会阻塞整个应用的渲染,这个时候唯一的解决办法是只能刷新整个页面才能恢复应用,React16引入新的错误处理机制,默认情况下,如果组件中抛出错误,这个组件会从组件树中卸载,从而避免整个应用的崩溃,组件的这种渲染方式和以前的比起来有一定的进步,但是用户的体验并不是十分额度友好,对此React16提供了另外一种更加友好的错误处理方式---错误边界(Error Boundaries)错误边界是能够捕获子组件的错误并对其做优雅处理的组件,优雅处理可以根据你的需求来设计,比如输出错误日志登,这又比直接卸载子组件要更加的友好。
说了这么多那什么是错误边界呢?定义了componentDidCatch(error,info)这个方法的组件将成为一个错误边界,接下来我们将创建一个错误边界组件ErrorBoundary并展示其用法
class componentDidCatch extends React.Component{
constructor(props){
super(props);
this.setState({
hasError:false
})
}
componentDisCatch(error,info){
//显示错误的ui
this.setState={hasError:true};
//输出错误日志
console.log(error,info);
}
render(){
if(this.state.hasError){
return <h1>Oops,something went wrong</h1>
}
return this.props.children
}
}
使用方法:
calss App extends component{
constructor(props){
super(props);
this.state={
user:{name:"React"}
};
}
//将user设置为null,模拟异常
onClick=()=>{
this.setState({
user:{name:null};
})
}
render(){
retrun(
<div>
<ErrorBoundary>
<Profile user={this.state.user}/>
</ErrorBoundary>
<button onClick={this.onClick}>更新</button>
</div>
)
}
}
当我们点击更新按钮后Profile结束到的user的name属性为空,程序会抛出错误TypeError,这个错误会被ErrorBoundary捕获,并在界面上显示错误提示,需要注意的是当使用create-react-app创建项目时,当程序发送错误,create-react-app会在页面上创建一个浮层显示错误,要观察ErrorBoundary的正确效果,需要先关闭浮层。
三,React16 的Portals特性让我们可以把组件渲染到当前组件以外的DOM节点上,这个特性典型的应用场景是渲染应用的全局弹窗,使用portals后,任意组件都可以将弹窗组件渲染到根节点上,以方便弹窗显示,Portals的实现依赖ReactDOM的一个新的API。
ReactDOM.createPortal(child,container)
第一个参数是可以被渲染的React节点,如react元素,由react元素组成的数组,字符串,contaiber是一个DOM元素,child被挂载到这个DOM节点上。
接下来我们创建一个Modal组件,这个组件使用ReactDOM.createPortal()在DOM根节点上创建一个弹窗:
class Modal extends Component{
constructor(props){
super(props);
//根节点下创建一个div节点
this.contsiner=document.createElement('div');
document.body.appendChild(this.contsiner);
}
componentWillUnmount(){
document.body.removeChild(this.container)
}
render(){
//创建的DOM树挂载到this.container指向的div节点下面
return ReactDOM.createPortal(
<div className="modal">
<span className="close" onClick={this.props.onClose}>
×
</span>
<div className="content">
{this.props.children}
</div>
</div>,
this.container
)
}
}
接下来我们有一个组件App并且在App组件当中使用Modal
class App extends Component{
constructor(props){
super(props);
this.state={showModal:false}
}
//关闭弹窗
closeModal=()=>{
this.setState({
showModal:false
});
}
render(){
return(
<div>
<h2>Dashboard</h2>
{this.state.showModal&&(
<Modal onCloase={this.closeModal}>Modal Dialog</Modal>
)}
</div>
)
}
}
export default App;
四:自定义的DOM属性
react16之前会忽略不识别的HTML和SVG属性,现在React会把不识别的属性传递给DOM元素,列如,react16之前,下面的react元素
<div custom-sttribute="something">在浏览器中的渲染结果为:</div>
如下为渲染结果:
<div>在浏览器中的渲染结果为:</div>
而在react16中渲染出来的结果为
<div custom-sttribute="something">在浏览器中的渲染结果为:</div>
继续更新中..........
如有不当之处,欢迎拍正。