在我努力学习 Javascript 的过程中,我一直在尝试实现一个所见即所得的代码编辑器。我没有实现 content-editablediv
或 a textarea
,而是从 Ajax.org 的 ACE 书中取出一片(相当多的一片)。
我有一个设置为 0 的侦听div
器tabIndex
来处理所有输入事件。编辑器的所有组件,如文本区域、光标和装订线,都是此侦听器的子项。自从实现鼠标事件处理程序以来,我一直有一个问题是焦点丢失在mousedown
事件上。显然,blur
即使mousedown
事件发生在侦听器中,事件也会被触发。
在注释掉某些方法调用并试图查看导致问题的确切原因后,我注意到罪魁祸首是render
方法。现在,我在每次输入后调用这个方法,所以焦点丢失很奇怪,特别是当我为mousedown
事件调用它时。在注释掉该render
方法blur
时,有事件时不会触发mousedown
事件。
更进一步,事实证明,在注释掉我替换innerHTML
文本容器的部分时,问题就消失了。同样,这很奇怪,因为我在replaceInnerHTML
函数的各个位置都使用了该render
函数,但问题似乎仅来自于特别更新 text div
。
这是 replaceInnerHTML 方法(我在这里发现的):
function replaceInnerHTML(el, html) {
var newEl = el.cloneNode(false);
newEl.innerHTML = html;
el.parentNode.replaceChild(newEl, el);
return newEl;
}
这是文本层的更新功能,省略不会出现此问题:
TextLayer.prototype.update = function(config) {
html = [];
var top = config.topRow;
var last = config.lastRow;
for(var i=top; i<=last; i++) {
var line = this._session.getLine(i);
if(line) {
html.push('<div class="line" style="height:'+this.$characterSize.height+'px;">');
this.renderLine(html, line);
html.push('</div>');
}
}
this._text = replaceInnerHTML(this._text, html.join(''));
this.setSize(config.totalWidth, config.scrollHeight);
};
为什么焦点会因为替换innerHTML
特定节点而变得模糊,而且只有在发生事件时才调用它mousedown
?
或者我在尝试调试时是否朝着完全错误的方向前进,而这个问题是由其他原因引起的?
编辑:
感谢 pimvdb,这里有一个重现问题的小提琴。http://jsfiddle.net/wG4Yy/39/
由于重组了事件上的节点,该blur
事件似乎触发了mousedown
。我不知道如何解决问题。我尝试过使用文档片段而不是 innerHTML,并且我也尝试过使用 安排更新setTimeout
,但都没有成功。
我应该怎么做才能解决问题?