DOM操作
操作底层DOM的使用场景:当需要与一个没有使用React的第三方类库进行整合,或执行一个React没有原生支持的操作时。
访问受控的DOM节点:
想要访问受React控制的DOM节点,首先必须能够访问到负责控制这些DOM的组件。这可以通过为子组件添加一个ref属性来实现。
eg:
var DoodleArea = React.createClass({
render: function () {
return <canvas ref="mainCanvas"/>;
}
});
这样可以通过this.refs.mainCanvas访问到<canvas>组件。同时必须保证每个子组件的ref值在所有子组件中是唯一的,如果有两个子组件ref值相同则操作将失效。
一旦通过this.refs.mainCanvas访问到canvas子组件,就可以通过它的getDOMNode()方法访问到底层的DOM节点。但不能在render方法中调用getDOMNode()。因为render方法完成并且React执行更新之前,底层的DOM节点可能不是最新的(甚至尚未创建)。直到组件被挂载才能调用getDOMNode()方法,即componentDidMount事件处理器被触发时。
注意:componentDidMount内部并不是getDOMNode()方法的唯一执行环境,事件处理器也可以在组件挂载后触发,所以也可以在事件处理器中调用getDOMNode().
使用this.refs.getDOMNode()方法会对React产生性能上的障碍,只有在没有其他方法能够实现需要的功能时才能考虑使用。
整合非React类库:
没有使用React构建的JavaScript类库,一些类库不需要使用DOM,如果要使用它们,保持状态和React的状态之间的同步是成功整合的关键。
eg:autocomplelte类库:
autocomplete({
target: document.getElementById("cities"),
data: [
"San Francisco",
"St. Louis",
"Amsterdam",
"Los Angeles"
],
events: {
select: function (city) {
alert("You have selected the city of " + city);
}
}
});
该autocomplete函数需要一个目标DOM节点、一个用作数据展现的字符串清单,以及一些时间监听器
使用该类库的React组件:
var AutocompleteCities = React.createClass({
render: function () {
/*/DOM节点*/
return <div id="cities" ref="autocompleteTarget"/>
},
getDefaultProps: function () {
return {
/*字符串清单*/
data: [
"San Francisco",
"St. Louis",
"Amsterdam",
"Los Angeles"
]
};
},
/* 事件监听器*/
handleSelect: function (city) {
alert("You have selected the city of " + city);
},
componentDidMount: function () {
autocomplete({
target: this.refs.autocompleteTarget.getDOMNode(),
data: this.props.data,
events: {
select: this.handleSelect
}
});
}
});
componentDidMount方法只会为每个节点调用一次。因此我们不用担心在一个节点上两次调用autocomplete方法产生的影响。
也就是说该组件可能被移除,然后在其他DOM节点上重新渲染,如果在componentDidMount方法内导致了DOM节点无法被移除,有可能导致内存泄漏或者其他问题。为确保此现象的发生,可以指定一个componentWillUnmount监听器,用于在组件的DOM节点移除时清理自身。
侵入式插件:
修改除了自己子元素以外的依附元素(如父元素)的插件。
面对这类侵入式插件,保护好React的最好方式就是把DOM操控权完全交给我们自己。在componentDidMount方法中做一些初始化工作。这里也需要去完成清理工作。
还需要进行处理更新。可通过两种方式触发:
-- 模拟卸载器而后重新挂载(更高效)
eg:
componentDidUpdate: function () {
this.componentWillUnmount();
this.componentDidMount();
}
-- 使用插件的更新操作API(更有效、清晰)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。