我想使用 React 创建一个类似于 JSFiddle 的 UI:
- HTML、CSS 和 JS 的面板
- 预览面板
- 一个更新预览的“运行”按钮
我想为 HTML、CSS 和 JS 面板使用 Microsoft 的Monaco 编辑器来获得语法高亮和自动完成功能。
我已经抽象出一个通用的 MonacoEditor 组件。我的组件层次结构如下所示:
<Root>
<div>HTML <MonacoEditor /></div>
<div>CSS <MonacoEditor /></div>
<div>JS <MonacoEditor /></div>
<button onClick={this.run}>Run</button>
<PreviewPanel />
</Root>
如果我在 Vanilla JS 中实现这个 UI,该run()
方法将调用getValue()
每个 Monaco 实例以从每个面板中提取全文并生成预览。
然而,这对于 React 来说变得很尴尬,因为该run()
方法不能在子组件的实例上调用方法。
一种解决方法是让MonacoEditor
道具onUpdate
在每次击键时触发。Root
当单击“运行”按钮时,该组件可以存储每个面板的临时内容。如果每个编辑器都是<textarea>
. 但这对摩纳哥来说不是首发。在每次击键时序列化编辑器的文本会使其变得非常慢。
我能想到的唯一其他方法是将“getter setter”传递给MonacoEditor
组件,例如:
class Root extends React.Component {
render() {
return (
<div>
<MonacoEditor setGetter={getter => this.getHTML=getter} />
<MonacoEditor setGetter={getter => this.getCSS=getter} />
<MonacoEditor setGetter={getter => this.getJS=getter} />
<button onClick={() => this.run()}>Run</button>
<PreviewPanel />
</div>
);
}
run() {
const html = this.getHTML();
const css = this.getCSS();
const js = this.getJS();
// ...
}
}
但这感觉非常尴尬,并且与单向数据绑定的想法背道而驰。有没有更好、更惯用的方法?