第三章:与DOM有关的日子

大部分情况下你不需要查询DOM来更新UI

在与DOM有关的日子里还是有些怀念的,怀念的也许不仅是技术,而是怀念自己从一棵小白菜成长起来的过程,怀念那个年代的某些时光。

PS:不怀旧了,言归正传。大部分情况下你应该只需要关注setState方法来改变组件的状态,但有时候情况往往比较特殊,比如input.focus的时候。React给大家提供了两种方式来引用DOM对象。

  • findDOMNode
  • refs

注意:不管是findDOMNode还是refs你都应该在componentDidMount方法中使用,且在componentWillUnmount方法中解除引用关系。

findDOMNode

当你需要获得React组件的DOM对象时,你必须使用findDOMNode方法。

render(){
  return (
    <Button
      ref="imageButton"
    ></Button>
  );
}
componentDidMount(){
  console.log(findDOMNode(this.refs.imageButton))
}

refs

在外还有另外的一种方式,在DOM元素上通过ref引用来获得访问DOM元素的能力。

render (){
  return (
    <div
      ref="book"
    >

    </div>
  );
}
componentDidMount (){
  console.log(this.refs.book)
}

ref也支持函数,你可以在函数中做一些逻辑操作:


constructor (props){
  this.book = null;
}
render (){
  return (
    <div
      ref={(v)=>{
        this.book = v;
      }}
    ></div>
  );
}

componentWillUnmount (){
  this.book = null;
}

正确的使用姿势

在刨除了正常的情况下,在React中直接引用DOM,你应该在componentDidMount中引用,然后在componentWillUnmount中解除引用。

且让我们看一看,在React中如何使用像Swiper这样的jQuery插件。

const findDOMNode = ReactDOM.findDOMNode;
const Button = Kodo.Button;
const imageArray = [
        'http://content.battlenet.com.cn/wow/media/screenshots/screenshot-of-the-day/warlords-of-draenor/warlords-of-draenor-ss0602-large.jpg',
        'http://content.battlenet.com.cn/wow/media/screenshots/screenshot-of-the-day/warlords-of-draenor/warlords-of-draenor-ss0601-large.jpg',
        'http://content.battlenet.com.cn/wow/media/screenshots/screenshot-of-the-day/warlords-of-draenor/warlords-of-draenor-ss0600-large.jpg',
        'http://content.battlenet.com.cn/wow/media/screenshots/screenshot-of-the-day/warlords-of-draenor/warlords-of-draenor-ss0599-large.jpg',
        'http://content.battlenet.com.cn/wow/media/screenshots/screenshot-of-the-day/warlords-of-draenor/warlords-of-draenor-ss0598-large.jpg'
      ];
class ImageSlide extends React.Component{
  constructor(props){
    super(props);
    this.imageSlideContainer = null;
    this.imageSlideObject = null;
    this.HandlerWithMe = this.handlerMe.bind(this);

  }
  handlerMe (e){
    console.log(this);
  }
  render (){
    return (
      <div className="container">
        <Button
          onClick={ this.HandlerWithMe }
          ref="imageButton"
        >click me</Button>
        <br/>
        <br/>
        <div
          className="swiper-container"
        >
          <div
            ref={(c)=>{
              this.imageSlideContainer = c;
            }}
            className="swiper-wrapper"
          >

          </div>
        </div>
      </div>
    );
  }
  componentDidMount (){
    console.log(this.imageSlideContainer);
    // console.log(this.refs.imageSlideContainer);
    let swiperHtml = imageArray.map((v)=>{
      return '<div class="swiper-slide"><img src='+v+' /></div>';
    }).join('');
    this.imageSlideContainer.innerHTML = swiperHtml;
    this.imageSlideObject = new Swiper('.swiper-container',{
      direction: 'vertical',
      loop: true,
      autoplay: 5000
    });

    // console.log(findDOMNode(this.refs.imageButton));
  }
  componentWillUnmount (){
    this.imageSlideContainer = null;
    this.imageSlideObject = null;
  }
}
ReactDOM.render((
    <ImageSlide />
),document.getElementById('app'));

像这样的方式,我建议将不适用虚拟DOM的部分,还是自己写成字符串插入到DOM中,如果你使用了React来描述,非常的不好控制状态。

results matching ""

    No results matching ""