#javascript #html
#javascript #HTML
Вопрос:
Я пытаюсь создать редактор кода с использованием HTML:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta http-equiv='X-UA-Compatible' content='IE=Edge'>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' href='style.css'>
</head>
<body>
<pre id='editor'><code contenteditable='true'></code></pre>
<script type='module'>
import { highlight } from './highlighter.js';
import { Caret } from './caret.js';
(() =>
{
const editor = document.querySelector('#editor code');
const caret = new Caret(editor);
highlight(editor);
editor.addEventListener('input', e =>
{
highlight(editor);
e.preventDefault();
});
editor.addEventListener('keydown', e =>
{
const TAB = 9;
const ENTER = 13;
switch (e.keyCode)
{
// ...
}
});
})();
</script>
</body>
</html>
highlighter.js:
import { Caret } from './caret.js';
export function highlight(editor)
{
// ...
const NORM = '#E6E6FA';
// ...
const Highlighter = {
source: editor.innerText,
start: 0,
curr: 0,
// ...
fin()
{
return this.curr >= this.source.length;
},
advance()
{
return this.source[this.curr ];
},
// ...
scan()
{
let result = '';
this.start = this.curr;
if (this.fin())
{
return null;
}
const char = this.advance();
let color = NORM;
switch (char)
{
// ...
}
return {
color,
text: this.source.substring(this.start, this.curr),
};
},
};
let result = '';
const caret = new Caret(editor);
const save = caret.getPos();
for (;;)
{
const lexeme = Highlighter.scan();
if (lexeme === null)
{
break;
}
const chars = lexeme.text.split('').map(
x => `<span style='color: ${lexeme.color};'>${x}</span>`);
result = chars.join('');
}
editor.innerHTML = resu<
caret.setPos(save);
};
<span><span>По сути, он берет текстовое содержимое пользовательского кода, сканирует его для создания лексем с данными о цвете, разбивает эти лексемы на символы, которые помещаются в теги с цветами, затем добавляет эти s к строке, для которой обновляется innerHTML редактора, и, наконец, курсор пользователя перемещаетсяверните его в правильное положение; это делается при вводе. Однако есть одна проблема: если пользователь вводит слишком быстро, введенный им текст может быть удвоен. Я пытался исправить это с помощью других типов прослушивателей событий и пытался просто использовать setInterval, но это не сработало вообще.
Ответ №1:
Из того, что вы описали
если пользователь вводит текст слишком быстро
и видя, что дорогостоящая в вычислительном highlight()
отношении функция вызывается при каждом изменении input
элемента
editor.addEventListener('input', e => {
highlight(editor); // <--
e.preventDefault();
});
Я бы предложил отменить этот призыв, чтобы выделить его. Вот хорошее объяснение отмены.
Попробуйте что-то вроде этого:
// Vanilla debounce: https://gist.github.com/peduarte/7ee475dd0fae1940f857582ecbb9dc5f
function debounce(func, wait = 100) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(this, args);
}, wait);
};
}
// ...
// adjust delay to find a balance between responsiveness and performance
const delay = 500;
const runHighlight = () => highlight(editor);
const debouncedHighlight = debounce(runHighlight, delay);
editor.addEventListener('input', e => {
e.preventDefault();
debouncedHighlight();
});
Комментарии:
1. Спасибо, это решение помогло.