使用 Backbone 作为 React 组件查看

Use Backbone View as React component

我有 backbone 控件,我想在将用 React 和 Redux 编写的新模块中重用。我非常不确定如何处理这个问题。我最初的想法是将这个 backbone 视图包装在一个 React 组件中。以我在示例项目中完成的类似方式:

import React from 'react'
import ReactDOM from 'react-dom';
import Backbone from 'backbone';

var Test  = Backbone.View.extend({

render: function () {
    this.$el.html("<p> If you see that it's working</p>");
    return this;
}
});

class TestComponent extends React.Component {

  backboneComponent;

constructor(props) {
    super(props);
    this.backboneComponent = new Test();
}

render(){
    return (<div dangerouslySetInnerHTML={{__html:   this.backboneComponent.render().el.innerHTML}} ></div>);
}
}

ReactDOM.render( <div>
   <TestComponent/>
</div>
,document.getElementById("root"));

所以这个东西有效,但由于这个危险的 SetInnerHtml 参数,我对它有了第二个想法。我也不确定如何解决将 redux 状态与 backbone 模型绑定的问题。

另一种方法是将 backbone 视图放入全局 window 对象,而不仅仅是从代码的 React-Redux 部分与它交互。但我也不确定。那么各位网友们,这个燃眉之急的问题你们有答案了吗?

另一种方法是让 React 组件渲染到 DOM,然后使用 React 组件渲染的 DOM 元素渲染 Backbone 元素。

https://jsfiddle.net/x8wnb5r8/

componentDidMount() {
  this.backboneComponent = new Test({
    el: ReactDOM.findDOMNode(this)
  }).render();    
}

有什么优势?

  • Backbone 在渲染时不强制执行许多规则,但它确实希望在任何视图的核心有一个工作的 DOM 元素,可以与之交互在视图的生命周期中。这种方法坚持认为。

  • 此解决方案不涉及 React 的虚拟 DOM,这意味着 Backbone 视图可以更新而无需触发任何 React 功能。这也应该比 DOM->虚拟 DOM->DOM 解决方案(与 innerHTML 一样)执行得更好。

  • Backbone模型事件仍然可以直接触发视图功能,不需要模型层在Backbone和React

    [=38之间交互=]

最终代码还需要 componentDidUpdate()componentWillUnmount() 处理程序。

这是一个更详细的版本,显示了 React 父组件 (OtherReactContainer) 和 Backbone 视图 (BBView) 更新的状态变化:https://jsfiddle.net/w11Ly493/

类似于 mikeapr4 的回答,在支持 refs 的 React 版本中,同样可以通过将 ref el 传递给 Backbone.View 的构造函数来完成:

// (React 16.4.2 with babel+classProperties)
class BackboneHost extends React.PureComponent {
  view = null;
  hostElRef = React.createRef();

  componentDidMount() {
    this.view = new MyBackboneView({ el: this.hostElRef.current });
    this.view.render();
  }

  componentWillUnmount() {
    this.view.remove();
  }

  render() {
    return <div ref={this.hostElRef} />;
  }
}