提问人:K. Russell Smith 提问时间:11/21/2020 更新时间:11/21/2020 访问量:45
语法荧光笔在更新文本时遇到问题
Syntax highlighter has trouble updating text
问:
我正在尝试使用 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>
荧光笔.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 = result;
caret.setPos(save);
};
基本上,它获取用户代码的文本内容,扫描它以生成带有颜色数据的词素,将这些词素拆分为字符,这些字符与颜色一起放入 <span> 标签中,然后将这些 <span>s 附加到编辑器的 innerHTML 更新到的字符串中,最后将用户的光标放回其正确的位置;这是在输入时完成的。但是,有一个问题:如果用户输入得太快,他们输入的文本可能会加倍。我试图用其他类型的事件侦听器来解决这个问题,并尝试简单地使用 setInterval,但它根本效果不佳。
答:
1赞
simmer
11/21/2020
#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();
});
评论
0赞
K. Russell Smith
11/21/2020
谢谢,这个解决方案确实有帮助。
评论