我目前正在将一个遗留的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元素上的用户交互(例如,单击和拖动复杂的路径对象),而没有一个响应是不会被察觉的。
所以我的问题是:我是否走上了一条会导致我被烧死的道路?我真的很喜欢反应,我渴望和脊梁说再见。我能够在一个周末毫无痛苦地移植我的大部分UI代码。我以前看过棱角,但看起来太复杂了,太固执己见了。
发布于 2018-05-08 21:58:15
你朝正确的方向前进了。当您需要使用外部的非react库来呈现react中的内容时,可以这样做:
componentDidMount()上启动插件实例,并将对插件实例的引用作为组件实例的属性添加。这将使您能够从其他方法调用实例的方法。componentDidUpdate()中的支柱变化做出反应。使用插件实例的引用来更新它。componentWillUnmount()中清除插件添加/计划/等的所有内容.例如事件侦听器、超时/间隔、在反应性树之外创建的DOM节点、正在进行的AJAX调用等.注:在反应16.3之前,标准方法是通过在shouldComponentUpdate()中返回false来防止道具/状态的更改,并对componentWillReceiveProps()中的道具变化作出反应。然而,后者正在走向被反对的道路上,而前者将是一种建议,而不是一种严格的命令。
这个(不工作)示例是基于当前的VexFlow教程松散的。
export default class ScoreComponent extends React.Component {
constructor(props) {
super(props);
// 1. create a ref to a DOM element
this.scoreElem = React.createRef();
...
}
componentDidMount() {
const { size } = this.props;
const elem = this.scoreElem.current;
// 2. add a reference to the plugin's instance, so you
// can call the plugin in other lifecycle methods
this.renderer = new VF.Renderer(elem, VF.Renderer.Backends.SVG)
renderer.resize(size.w, size.h);
this.context = renderer.getContext();
...
}
componentDidUpdate (prevProps) {
// 3. if the props effect the plugin
// do something with the plugin
// for example:
const { size } = this.props;
if(size !== prevProps.size) this.renderer.resize(size.w, size.h);
}
componentWillUnmount() {
// 4. teardown:
// run VexFlow destroy method if available
// remove non react event listeners
// clear timeouts and intervals
// remove DOM nodes rendered outside of react container
// cancel ongoing AJAX calls
// etc...
}
render() {
// 5. use only ref on the returned element, any use of properties/state might rerender the element itself.
return (
<div className="score" ref={this.scoreElem}></div>
);
}
}https://stackoverflow.com/questions/50240053
复制相似问题