React 16.0中的新特性——portal及其注意点

来源:互联网 发布:人工智能的危害英文 编辑:程序博客网 时间:2024/06/05 18:34

简要介绍:React16.0中发布了很多新特性,我们来看portal,React提供了一个顶级API—portal,用来将子节点渲染到父节点之外的dom节点

1.基本用法

(1)在React15.X版本中,我们只能讲子节点在父节点中渲染,基本用法如下:

render() {  // React需要创建一个新的div来包含子节点  return (    <div>      {this.props.children}    </div>  );}

但是如果需要将子节点插入到父节点之外的dom呢,React15.x及之前都没有提供这个功能的API。

(2)React16.0中的portal

render() {  // React不需要创建一个新的div去包含子元素,直接将子元素渲染到另一个  //dom节点中  //这个dom节点可以是任何有效的dom节点,无论其所处于dom树中的哪个位置   return ReactDOM.createPortal(    this.props.children,    domNode,  );}
  1. Portal中的dom节点必须是有效的节点

ReactDOM.createPortal函数的第二个参数,是被插入的dom节点,并且这个dom节点是有效的节点,而不能是通过ref获得并传递的virtual dom节点,举例来说:

class MyTestableClass extends React.Component{    constructor(){      super();      this.state={        sprop:''      }    }    render(){      return <div>              <Left ref={(input)=>{this.left=input}}>我是左边的信息</Left>              <Right sprop={this.state.sprop}>我是右边的信息</Right>      </div>    }    componentDidMount(){       var left=this.left;       var state=this.state;       this.setState({         sprop:left       })    }}ReactDom.render( <MyTestableClass/>,document.getElementById('app'))

在整个组件中,我们将ref获得的子节点Left,通过props传递给了子节点Right,然后在Right子节点中,通过:

class Right extends React.Component{   constructor(){     super();   }   render(){     var props=this.props;     if(this.props.sprop){       return <div className="right">{this.props.children}</div>     }else{       return ReactDOM.createPortal(            this.props.children,            this.props.sprop             );     }   }  componentWillReceiveProps(nextProp){    console.log(nextProp.sprop);  }}

我们尝试将子节点插入到通过props传递过来的另一个节点this.props.sprop中,因为this.props.sprop并不是一个valid dom node,它是一个virtual dom node,因此会报错:

//Target container is not a DOM element.

3.通过Portals实现事件冒泡

虽然一个portal可以插入到任何一个存在dom树中,但是通过Portal节点插入到其他dom中的节点,跟其他的React普通的子节点表现相同。在父节点下,通过Portal插入的子节点也可以共享context。

对于事件冒泡,从Portal节点中触发的事件,可以在任何包含它的节点中冒泡,即使这个包含节点不是Portal节点的直接祖先元素,比如下面的HTML结构中:

<html>  <body>    <div id="app-root"></div>    <div id="modal-root"></div>  </body></html>

在上面的HTML结构中,通过Portal, 在“modal-root”中出发的事件,也可以冒泡到“app-root”中。

原创粉丝点击