Вот что происходит:
- Инициализация:
Терминал инициализируется с помощью 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:
Обеспечение обновления DOM перед подгонкой, но проблема не устранена.
Код: Выделить всё
await nextTick(); fitAddon.fit(); - Отложена установка 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