我一直在搜索一个关于在使用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
。
NL;PR:
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(它避免了第一次呈现时高度只有大约10像素的情况):
.editor{
height: 100%;
}
首次测试:v0.10.1,最后测试:v0.32.1
注意:< v0.20.0:该机制不会监听其容器大小的更改,而是进行轮询。 [API]
@nrayburn-tech(Monaco Editor的贡献者):版本0.20在所有浏览器中使用MutationObserver。版本0.21及更高版本在支持的浏览器上使用ResizeObserver,否则将使用轮询作为后备方案。
automaticLayout
设置为true
并将编辑器的height
设置为100%
时,编辑器不会增长/调整大小。正如您所指出的,如果我不设置height
,则第一次呈现编辑器为~`10px`,但仍然不会调整大小。 - Trevor对于任何在基本的 Web 应用程序(html、css、javascript)中遇到此问题的人,我已经找到了解决我所遇到的调整大小问题的方法。
我在可调整大小的 flex 容器内使用了 Monaco 编辑器。它只会增加宽度,不会缩小宽度,并且垂直调整大小似乎无法正常工作。
如果您使用 Monaco 配置 "automaticLayout: true" 和以下 CSS,则它似乎可以按预期调整大小:
.monaco-editor { position: absolute !important; }
我尝试了最大宽度 99% 的技巧,但当将宽度增加到页面边缘附近时,会导致延迟效果和卡顿。
window.onresize
和ResizeObserver
,因为我担心automaticLayout
似乎使用了一个间隔或其他什么...如果你现在也在这个阶段...不要像我一样做,只需这样做就可以了哈哈。完美无缺地运行。 - undefined如果您有编辑器的引用,您只需在某些调整大小事件上调用editor.layout()
。例如,在窗口调整大小时:
window.onresize = function (){
editor.layout();
};
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,这样我们就可以安全地查询父元素的尺寸而不会受到子元素(编辑器)对其大小的影响。然后我们可以将编辑器与新的父元素尺寸匹配。由于这个过程在单个帧中完成,因此不应出现闪烁或延迟。
automaticLayout: false
时,小地图出现了一些闪烁,但是使用这种方法却很流畅...奇怪。 - fluffels这是一个旧问题,但仍然存在这个问题,我使用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容器: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秒钟检测一次,并确保只注册一次。我注意到monaco自动重新布局的调整大小间隔为100毫秒 - 在我看来这太频繁了。
在此处查看实际效果:https://typescript-api-playground.glitch.me/?example=2