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
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение