我目前正在将一个传统的BackboneJS应用移植到ReactJS。该应用使用VexFlow,JavaScript音乐符号渲染引擎。我遇到的一个主要问题是VexFlow以与D3类似的方式将所有内容呈现给SVG。将D3与React结合起来有很多信息,我正在遵循使用空的React ref
元素作为我的VexFlow渲染的目标的情况下的一般做法,这一切都发生在componentDidMount
:
export default class ScoreComponent extends React.Component {
constructor(props) {
super(props);
// Create a 'ref' object, which allows us to reference the React DOM
// element we create in the render method.
this.scoreElem = React.createRef();
...
}
componentDidMount() {
var score = this.score;
var elem = this.scoreElem.current;
score.setElem(elem).render(); // <- All VexFlow rendering happens here...
...
}
render() {
return (
<div className="score" id={this.props.scoreId} ref={this.scoreElem}></div>
);
}
}
虽然这很有效,但它让我感到很不舒服,特别是因为我还需要添加大量的jQuery代码来处理SVG元素上的用户交互(例如,单击并拖动复杂的路径对象),其中没有一个是React请注意。
所以我的问题是:我是否会走上一条会导致我被烧伤的道路?我真的很喜欢React,我很想跟Backbone说再见。我能够在一个周末轻松地移植我的大部分UI代码。我过去曾看过Angular,但看起来太复杂了,而且很自以为是。
答案 0 :(得分:1)
你正朝着正确的方向前进。当您需要使用外部非反应DOM库来呈现内容时,这是可行的方法:
componentDidMount()
上启动插件实例,并在插件的实例上添加对插件实例的引用作为属性。这将使您能够从其他方法调用实例的方法。componentDidUpdate()
中的更改进行反应。使用插件实例的引用来更新它。componentWillUnmount()
中清除插件添加/预定/等等的所有内容...例如事件侦听器,超时/间隔,在React树外部创建的DOM节点,正在进行的AJAX调用等等...... 注意:在React 16.3之前,标准方法是通过返回$.getJSON("menu.json")
.done(function(obj) {
console.log(obj.name);
});
中的false
并对{{1}中的道具变化作出反应来防止重新渲染道具/状态变化}}。然而,后者是被弃用的方式,而前者将是一个建议,而不是将来的严格订单。
此(非工作)示例基于当前VexFlow tutorial:
shouldComponentUpdate()