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

简要介绍: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节点中触发的事件,虽然可能改变了节点所处的位置,但是在HTML结构中的父包含节点是可以拿到这个事件的。

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

在上面的HTML结构中,通过Portal, 在Button真实位置是包含在“modal-root”下,但是因为在HTML的结构中Button所在的父节点的HTML结构是包含“app-root”中的,因此在“modal-root”中出发的事件,也可以冒泡到“app-root”中。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值