我一直在寻找有关在互联网上使用Monaco Editor的字段时是否可以模仿 html 标签 textarea 的大小调整的讨论,但我找不到回答我的问题的人。
我在React应用程序中使用monaco-editor npm 包。你知道这是否容易实现吗?
先感谢您!
解决方案
使用纯 css 我选择了目标 html 元素并添加了这些属性:
div {
resize: vertical;
overflow: auto;
}
我一直在寻找有关在互联网上使用Monaco Editor的字段时是否可以模仿 html 标签 textarea 的大小调整的讨论,但我找不到回答我的问题的人。
我在React应用程序中使用monaco-editor npm 包。你知道这是否容易实现吗?
解决方案
使用纯 css 我选择了目标 html 元素并添加了这些属性:
div {
resize: vertical;
overflow: auto;
}
TL;DR:添加automaticLayout: true
到编辑器的配置中。
荷兰;公关:
Monaco 有一个内置的自动调整大小到父容器的功能:
createEditorWithAutoResize(){
this.editor = monaco.editor.create(
this.editorDiv.current, {
value: "var x = 0;",
language: 'javascript',
automaticLayout: true // <<== the important part
}
);
}
componentDidMount(){this.createEditorWithAutoResize();}
constructor(props){super(props); this.editorDiv = React.createRef();}
render(){return <div ref={this.editorDiv} className="editor" ></div>}
以及编辑器的 CSS(它避免了第一次以 10px 的高度渲染编辑器):
.editor{
height: 100%;
}
第一次测试: v0.10.1,最后一次测试: v0.32.1
注意: < v0.20.0:该机制不会监听其容器大小的变化,而是轮询它们。
@nrayburn-tech(摩纳哥编辑的贡献者):0.20 版对所有浏览器都使用 MutationObserver。0.21 及更高版本在支持的浏览器上使用 ResizeObserver,否则,它使用轮询作为后备。
如果您对编辑器有参考,您可以调用
editor.layout()
一些调整大小事件。例如,在调整窗口大小时:
window.onresize = function (){
editor.layout();
};
这是个老问题,但是用react-resize-detector解决了这个问题
基于ResizeObserver它完全符合需要(检查浏览器兼容性)
组件示例:
import React, { Component } from 'react';
import ReactResizeDetector from 'react-resize-detector';
import * as monaco from 'monaco-editor';
class Editor extends Component {
constructor(props) {
super(props)
this.state = {
width: 0,
height: 0,
}
this.editor_div = React.createRef()
this.handle_rezise = this.handle_rezise.bind(this);
}
componentDidMount() {
const editor_model = monaco.editor.createModel('', 'sql');
this.monaco_editor = monaco.editor.create(this.editor_div.current, this.props.editorOptions);
this.monaco_editor.setModel(editor_model);
}
componentWillUnmount() {
this.monaco_editor && this.monaco_editor.dispose();
}
handle_rezise(width, height) {
this.monaco_editor.layout({ height, width });
}
render() {
return(
<div
className="editor-container"
style={{ height: '100%' }}>
<ReactResizeDetector
handleWidth
handleHeight
onResize={ this.handle_rezise }
refreshMode="debounce"
refreshRate={100} />
<div
className="editor"
ref={ this.editor_div }
style={{ height: '100%' }} />
</div>
)
}
}
export default Editor;
希望有帮助
在我的情况下,我使用的是确切的 CSS,但虽然 automaticLayout: true 有效,但我发现过度杀伤(似乎汇集了 DOM 100ms 间隔,并且我在文档中打开了几个编辑器。所以我最终手动实现它:
以防万一,我的需求有所不同:我希望用户以标准方式调整容器的大小,并且在库和性能方面便宜(在代码和性能方面)。这就是我所做的:
CSS容器:resize: vertical; overflow: auto
这个js:
function installResizeWatcher(el, fn, interval){
let offset = {width: el.offsetWidth, height: el.offsetHeight}
setInterval(()=>{
let newOffset = {width: el.offsetWidth, height: el.offsetHeight}
if(offset.height!=newOffset.height||offset.width!=newOffset.width){
offset = newOffset
fn()
}
}, interval)
}
const typeScriptCodeContainer = document.getElementById('typeScriptCodeContainer')
typeScriptCodeEditor = monaco.editor.create(typeScriptCodeContainer, Object.assign(editorOptions, {value: example.codeValue}))
installResizeWatcher(typeScriptCodeContainer, typeScriptCodeEditor.layout.bind(typeScriptCodeEditor), 2000)
是的,间隔 2 秒,并确保它只注册一次。我看到摩纳哥的自动重新布局在 100ms 上有一个调整大小间隔 - 恕我直言,这太多了。
看看它的实际效果:https ://typescript-api-playground.glitch.me/?example=2
对于后代,我得到的解决方案是设置automaticLayout: false
,以便我可以在调整大小事件侦听器中执行所有布局。
const placeholder = document.getElementById('placeholder')
const editor = monaco.editor.create(placeholder, {
value: '// hello world',
language: 'javascript',
automaticLayout: false // or remove, it defaults to false
})
// we need the parent of the editor
const parent = placeholder.parentElement
window.addEventListener('resize', () => {
// make editor as small as possible
editor.layout({ width: 0, height: 0 })
// wait for next frame to ensure last layout finished
window.requestAnimationFrame(() => {
// get the parent dimensions and re-layout the editor
const rect = parent.getBoundingClientRect()
editor.layout({ width: rect.width, height: rect.height })
})
})
通过首先将编辑器布局减少到 0,我们可以安全地查询父元素的尺寸,而不会影响其大小。然后我们可以将编辑器与新的父维度匹配。由于这发生在单个帧上,因此不应出现闪烁或延迟。