Vue.js xterm.js FitAddon вызван слишком рано, размер терминала не изменяется до правильных размеровJavascript

Форум по Javascript
Anonymous
Vue.js xterm.js FitAddon вызван слишком рано, размер терминала не изменяется до правильных размеров

Сообщение Anonymous »

Я работаю над приложением Vue.js, в которое интегрирую xterm.js для отображения журналов терминала. Я использую FitAddon, чтобы гарантировать правильное изменение размеров терминала внутри контейнера. Однако я столкнулся с проблемой, из-за которой метод fitAddon.fit() вызывается слишком рано. В результате размеры терминала изначально установлены равными нулю, и терминал не вписывается правильно, пока я вручную не изменю размер окна браузера, что затем запускает надстройку fitAddon для правильной работы.
Вот что происходит:
  • Инициализация:
    Терминал инициализируется с помощью fitAddon.fit() во время onMounted.
    На этом этапе у TerminalContainer значения offsetWidth и offsetHeight равны 0, поэтому терминал не отображается должным образом.
  • Изменение размера вручную:
    Когда я вручную изменяю размер окна, handleResize запускается метод, вызывающий fitAddon.fit() снова.
    На этот раз размер терминала изменяется правильно, поскольку контейнер имеет допустимые размеры.
Соответствующие фрагменты кода:
logs.vue

Код: Выделить всё







[img]https://static.mobileye.com/zorro/img/no_data_image.png[/img]
Can’t find logs





import {
ref,
onMounted,
watch,
nextTick,
onBeforeUnmount,
} from 'vue';
import { Terminal } from '@xterm/xterm';
import { FitAddon } from '@xterm/addon-fit';
import debounce from 'lodash/debounce';
import { logsObserver, logsObserverHttp, highlightGrep } from '../../../services/logs.service';
import { escapeRegExp } from '../../../services/utils.service';

const props = defineProps({
logsData: { type: Object, required: true },
});

const search = ref('');
const terminalContainer = ref(null);
const isLoading = ref(true);
const logsExists = ref(false);
const grep = ref('');
const fetchedLogs = ref([]);

let term = null;
let fitAddon = null;
let subscription = null;

watch(search, (value) => {
setGrep(value);
});

const setGrep = debounce((value) => {
grep.value = value;
}, 200);

const initializeTerminal = () => {
term = new Terminal({
scrollback: 999999,
allowTransparency: true,
convertEol: true,
theme: {
background: 'white',
foreground: '#495763',
selectionBackground: '#0000ff55',
},
});

fitAddon = new FitAddon();
term.loadAddon(fitAddon);
term.open(terminalContainer.value);

fitAddon.fit();

term.attachCustomKeyEventHandler((ev) => {
if (ev.ctrlKey && ev.code === 'KeyC' && ev.type === 'keydown') {
const selection = term.getSelection();
if (selection) {
navigator.clipboard?.writeText(selection);
return false;
}
}
return true;
});
};

const handleResize = debounce(() => {
if (fitAddon) {
fitAddon.fit();
}
}, 2000);

onMounted(async () => {
window.addEventListener('resize', handleResize);
});

const subscribeToLogsObserver = (url) => {
return logsObserver(url)
.subscribe({
next: (line) => {
term.write(line + '\r\n');
isLoading.value = false;
},
error: (err) => {
console.error(err);
isLoading.value = false;
}
});
}

watch(() => terminalContainer.value, async (newVal) => {
isLoading.value = true;
await nextTick();

initializeTerminal();

subscription = subscribeToLogsObserver(props.logsData.url);
});

onBeforeUnmount(() =>  {
window.removeEventListener('resize', handleResize);
if (term) {
term.dispose();
term = null;
}

if (subscription) {
subscription.unsubscribe();
subscription = null;
}
});



.logsContainer {
/* styles */
}

Проблема:
  • FitAddon.fit() вызывается сразу после term.open(terminalContainer.value), но на этом этапе offsetWidth и offsetHeight TerminalContainer равны 0.
  • Следовательно, терминал не отображается с правильными размерами.
  • Только после изменения размера окна терминал вписывается правильно.
Что я пробовал:
  • Использование nextTick:

    Код: Выделить всё

    await nextTick();
    fitAddon.fit();
    
    Обеспечение обновления DOM перед подгонкой, но проблема не устранена.
  • Отложена установка fitAddon. fit() с setTimeout:

    Код: Выделить всё

    setTimeout(() => {
    fitAddon.fit();
    }, 100);
    
    Ненадежно и иногда еще слишком рано.
Вопрос :
Как я могу гарантировать, что fitAddon.fit() вызывается после того, как терминал-контейнер полностью визуализируется и имеет допустимые размеры в Vue .js-компонент? Я хочу, чтобы терминал инициализировался с правильным размером, не требуя изменения размера окна вручную.
Дополнительная информация:
  • Версия Vue.js: 3.x
  • Версия xterm.js: Последняя
  • Ожидаемое поведение: терминал правильно помещается в контейнер при инициализация.
  • Наблюдаемое поведение: размеры терминала изначально равны 0 и корректно изменяются только после изменения размера окна вручную.


Подробнее здесь: https://stackoverflow.com/questions/793 ... the-correc

Вернуться в «Javascript»