与第三方库协同
React可以用于任何web应用中。它可以被嵌入到其他应用,且需要足以,其他的应用也可以嵌入到React中。
集成带有DOM操作的插件
React不理会React自身之外的DOM操作。它根据内部虚拟DOM来决定是否需要更新,而且如果同一个DOM节点被另一个库操作了。React会觉得困惑而且没有办法恢复。 这并不意味着React与其他操作DOM的方式不能结合,也不一定结合困难,只不过需要你去关注每个库所做的事情。 避免冲突的最简单方式就是防止React组件更新。你可以渲染无需更新的React元素,比如一个空的<div />。
如果解决这个问题
一个用于通用的jQuery插件的wrapper。 添加一个ref到这个根DOM元素上,在componentDidMount中,我们能够获取它的引用这样我们就可以把它传递给jQuery插件了。 为了防止React在挂载之后去触碰这个DOM,我们会从render()函数中返回一个空的<div />。这个<div />元素既没有属性也没有子元素,所以React没有理由去更新它,使得jQery插件可以自由的管理这部分的DOM:
class SomePlugin extends React.Component {
componentDidMount(){
this.$el = $(this.el);
this.$el = SomePlugin();
}
componentWillUnmount(){
this.$el.SomePlugin('destroy')
}
render(){
return <div ref={(el) =>this.el=el} />
}
}注意我们同时定义了componentDidMount和componentWillUnmount生命周期函数。许多jQuery插件绑定事件监听到DOM上,所以在componentWillUnmount中注销监听是很重要的。如果这个插件每没有提供一个用于清理的方法,你可能会需要自己来提供一个,为了避免内存泄露要记得吧所有插件注册监听都移除掉。
和其他视图库集成
得益于ReactDOM.render()的灵活性,React可以被嵌入到其他的应用中。 虽然React通常被用来在启动的时候加载一个单独根React组件到DOM上,ReactDOM.render()同样可以在UI的独立部分上多次调用,这些部分可以小到一个按钮,也可以大到一个应用。
利于用React替换基于字符串的渲染
在旧的web应用中有一个通用的模式就是使用一个字符串描述DOM块,并且通过类似的html方法插入到DOM中。代码库中的这种例子是非常适合引入React的。直接把基于字符串渲染写成React组件即可。
$("#container").html("<button id='btn'>Say Hello</button>")
$("#btn").click(function(){
alert('Hello')
})可以使用React组件重写:
function Button(){
return <button id="btn" > Say Hello </button>
}
ReactDom.render(
<Button ></Button>,
document.getElementById('container'),
function(){
$('#btn').click(function(){
alert('Hello!')
})
}
)从这起你可以开始把更多的逻辑移动到组件中,并开始应用更多通用的React实践。例如,在组建中最好不要依赖id,因为一个组件可能会被渲染多次。相反的,我们会使用React事件系统并且直接注册click处理函数到React的<Button>元素:
function Button(props){
return <button onClick={props.onClick}> Say Hello</button>
}function HelloButton(){
function handleClick(){
alert('hello')
}
return <Button onClick={handleClick} />
}ReactDOM.render(
<HelloButton />,
document.getElementById('container'),
)只要你喜欢你可以有不限数量的这种独立组件,并且使用ReactDOM.render()吧他们渲染到不同的容器中。逐渐的,随着你把越来越多的应用转化到React,你就可以吧他们结合成更大的组件,并且吧ReactDOM.render的调用移动到更上层的结构。
把React嵌入到Backbone视图
Backbone视图通常使用HTML字符串,或者产生字符串的模板函数,来创建DOM元素的内容,这个过程,同样的可以通过渲染一个React组件来替换掉。 如下,我们会创建一个名为ParagraphView的Backbone视图。他会重载Backbone的render()函数来渲染一个React<Paragraph />组件到Backbone(this.el)提供的DOM元素中,同样使用ReactDOM.render():
function Paragraph(props) {
return <p>{props.text}</p>;
}
const ParagraphView = Backbone.View.extend({
render() {
const text = this.model.get('text');
ReactDOM.render(<Paragraph text={text} />, this.el);
return this;
},
remove() {
ReactDOM.unmountComponentAtNode(this.el);
Backbone.View.prototype.remove.call(this);
}
});在remove方法中我们也需要调用ReactDOM.unmountComponentAtNode()以便在它解除的时候React清理组件树相关的事件处理的注册和其他资源。 当一个组件在React树中从内部删除的时候,清理工作是自动完成;但是因为我们现在手动(非React)移除整个树,我们必须手动调用这个方法。
和Model层集成
虽然通常是推荐使用单向数据流动的,例如React state,Flux或者Redux。React也可以使用一个其他框架和库的Model层。
在React组件中使用Backbone的Model
在React组件中使用Backbone的model和collection最简单的方法就是监听多种变化事件并且手动强制触发一个更新。 负责渲染model的组件会监听change事件,而负责渲染collection的组件需要监听add和remove事件。在这两种情况中,调用this.forceUpdate()来使用心得数据重新渲染组件。
class Item extend React.Component{
constructor(props){
super(props)
this.handleChange=this.handleChange.bind(this);
}
handleChange(){
this.forceUpdate()
}
componentDidMount(){
this.props.model.on('change',this.handleChange)
}
componentWillUnmount(){
this.props.model.off('change',this.handleChange)
}
render(){
return <li>{this.props.model.get('text')}</li>
}
}class List extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
}
handleChange() {
this.forceUpdate();
}
componentDidMount() {
this.props.collection.on('add', 'remove', this.handleChange);
}
componentWillUnmount() {
this.props.collection.off('add', 'remove', this.handleChange);
}
render() {
return (
<ul>
{this.props.collection.map(model => (
<Item key={model.cid} model={model} />
))}
</ul>
);
}
}从model提取数据
我们会链接一个 NameInput React 组件到一个 Backbone model,并且每当输入框变化时更新它的 firstName 属性:
function NameInput(props) {
return (
<p>
<input value={props.firstName} onChange={props.handleChange} />
<br />
My name is {props.firstName}.
</p>
);
}const BackboneNameInput = connectToBackboneModel(NameInput);function Example(props) {
function handleChange(e) {
props.model.set('firstName', e.target.value);
}
return (
<BackboneNameInput
model={props.model}
handleChange={handleChange}
/>
);
}const model = new Backbone.Model({ firstName: 'Frodo' });
ReactDOM.render(
<Example model={model} />,
document.getElementById('root')
);你可以通过在生命周期方法中订阅其更改并,并选择性地,拷贝数据到本地 React state,来将 React 用于任何 model 库。
