Редактор Monaco с динамическим изменением размера

Я искал дискуссию о том, можно ли имитировать изменение размера текстового поля тега html при использовании поля Monaco Editor по всему Интернету, но я не нашел ни одного, отвечающего на мой вопрос.

Я использую npm-пакет monaco-editor в приложении React. Вы хоть представляете, легко ли это реализовать?

Заранее спасибо!

РЕШЕНИЕ
С помощью чистого css я выбрал целевой элемент html и просто добавил эти свойства:

div {
  resize: vertical;
  overflow: auto;
}

person elenaHristova    schedule 30.10.2017    source источник
comment
Я предлагаю вам ответить на свой вопрос в разделе ответов, а не просто редактировать ответ, и принять его. Было бы лучше.   -  person Satnam Sandhu    schedule 01.01.2019
comment
Это вызывало у меня огромную головную боль. Использование monaco-response заняло 5 минут и по умолчанию реагирует.   -  person Parm    schedule 20.08.2020


Ответы (4)


TL; DR: добавьте automaticLayout: true в конфигурацию вашего редактора.

NL; PR:

В Monaco есть встроенная функция автоматического изменения размера до родительского контейнера:

React> = 16.3.0 (рекомендуется)

constructor(props){super(props); this.editorDiv = React.createRef();}

render(){
 return <div ref={this.editorDiv} className="editor" ></div>
}

componentDidMount(){
 let editor = monaco.editor.create(this.editorDiv.current, {
        value: "var x = 0;",
        language: 'javascript',
        automaticLayout: true // the important part
      });
}

React ‹16.3.0

render(){
 return <div ref={el=>{this.editorDiv = el}} className="editor" ></div>
}
 // I use this configuration in the editor:
componentDidMount(){
 let editor = monaco.editor.create(this.editorDiv, {
        value: "var x = 0;",
        language: 'javascript',
        automaticLayout: true // the important part
      });
}

И CSS для редактора (он позволяет избежать рендеринга редактора в первый раз с высотой примерно 10 пикселей):

.editor{
 height: 100%;
} 

Монако Версия: ^ 0.10.1, последнее тестирование: 0.20.0

Примечание. ‹Версия 0.20.0: механизм не отслеживает изменения размера контейнера, он опрашивает их.

@ nrayburn-tech (участник редактора Монако): Версия 0.20 использует MutationObserver для всех браузеров. Версия 0.21 и более поздние версии используют ResizeObserver в поддерживаемых браузерах, в противном случае он использует опрос как запасной вариант.

person David I. Samudio    schedule 07.11.2017
comment
Это не рекомендуется, если вам нужна производительность. github.com/Microsoft/monaco-editor/issues/28 - person atilkan; 10.01.2019
comment
Вы читали записку? опрос против прослушивания? ссылка на официальную документацию? - person David I. Samudio; 26.06.2019

если у вас есть ссылка на редактор, вы можете просто вызвать editor.layout() для некоторого события изменения размера. Например, при изменении размера окна:

window.onresize = function (){
    editor.layout();
};
person SimperT    schedule 28.11.2017

это старый вопрос, но решите проблему и решите ее с помощью response-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;

Надеюсь, это поможет

person Naej56    schedule 18.04.2019

В моем случае я использую именно этот CSS, но, хотя automaticLayout: true работает, я обнаружил излишек (похоже, объединяет интервал DOM 100 мс, и у меня есть несколько редакторов, открытых в документе. Итак, я закончил реализацию его вручную:

на всякий случай, мои потребности другие: я хочу, чтобы пользователь изменил размер контейнера - стандартным способом и дешево (как по коду, так и по производительности) по библиотекам и производительности. Вот что я сделал:

контейнер 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 секунды и убедитесь, что он регистрируется только один раз. Я вижу, что есть / был интервал изменения размера в 100 мс для автоматического реле в Монако - ИМХО, это слишком.

Посмотрите на это в действии: https://typescript-api-playground.glitch.me/?example=2

person cancerbero    schedule 21.06.2018