第三章:与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来描述,非常的不好控制状态。