innerText 操作 textarea 的 “坑”

原创
2017/03/27 18:29
阅读数 2.1K

这两天正在把 CodeMirror 融入 编辑器。。。结果发现了奇怪的现象: textarea 内正常的换行居然变成了<br>

以前从未出现过这种事情,难道是 Chrome 57(最新版)出现了 bug?

 

找了一下 FireFox 居然是这样, 再看 Chrome 49 还是这样。。。

看来不是最新版的问题,还是在自己的代码中找原因吧....

首先要了解 textarea 操作的几个特性:

  • 对于现在最新版的浏览器中  innerHTML / innerText / textContent 这几个方法都可以操作 textarea 内容
  • 对于旧版的浏览器中 FireFox 是不能使用 innerText 方法的(现在就不管这个了)
  • 一旦针对 textarea 使用了 value 方法 或 用户在 textarea 内输入内容后, innerHTML / innerText / textContent 这几个方法都不会影响 textarea 看到的值,当然也不会影响 value 的数据了

之前操作 textarea 部分的代码如下:

// 这是在保存编辑内容时,为了把 textarea 的内容正确保存时,必须要把 value 赋值给 html 内

// 为了处理 旧版 Firefox 兼容
textType = (obj.innerText === undefined ? 'textContent' : 'innerText');
if (obj.value !== obj[textType]) {
    obj[textType] = obj.value;
}

于是立刻找到问题所在:innerText

在编辑器内对于 textarea 只要使用 innerText 设置的值,'\n' 全部都会变成 '<br>'

不可思议的情况:

为什么以前从来没有发现过这个问题?? 为了谨慎着手,制作一个干干净净的 html 页面,只有一个 textarea,使用 innerText 设置数据,居然全都正常了。。OMG,难道是 CodeMirror 的 bug??赶紧打开 CodeMirror 提供的 Demo,直接操作对应的 textarea 全都出现 <br>!!看看源码吧, CodeMirror 内没有什么 innerText 相关的代码。。。太奇怪了吧??沉思中。。。

剧情反转:

最后只有终极法宝了,把出现问题的页面删除 script、删除 style,删除多余的,只留下 textarea,问题依然存在,然后创建一个新的 textarea,innerText 操作正常。这时恍然大悟,两个 textarea 唯一的区别就是 'display:none'

<textarea id="t01" style="display:none"></textarea>
<textarea id="t02" style="visibility:hidden"></textarea>
<textarea id="t03" ></textarea>

针对这 3 个 textarea 做如下测试:

document.querySelector('#t01').innerText = '555\n666';
document.querySelector('#t02').innerText = '555\n666';
document.querySelector('#t03').innerText = '555\n666';

可以看到 只有 display 为 none 的时候,数据出现了异常:

这样导致的直接错误是,获取整个 body 的 html时, textarea 内的数据异常了:“<textarea id="t01" style="display:none">555<br>666</textarea>”,这个 <br> 会直接导致编辑内容重新展示时出现异常。

不过对于 innerHTML 、textContent 操作均未发现异常。

问题解决:

找到了病根儿就好办了,针对这种情况调整一下代码即可:

textType = (obj.textContent === undefined ? 'innerText' : 'textContent');
if (obj.value !== obj[textType]) {
    obj[textType] = obj.value;
}

反思:

绝大部分界面操作都是直接让用户直接在 textarea 内输入,保存时从 textarea 的 value 内获取数据,像我们这种把编辑器内再融入 CodeMirror 的情况是很少见的,我可以尝试去 chrome 上提交一下 bug,看看是否能得到什么回复。。。拭目以待

https://bugs.chromium.org/p/chromium/issues/detail?id=705478

大结局再次反转:

Chrome 的技术人员答复了我提交的 bug

原文如下:

Safari and Firefox has the same behavior.

This behavior is defined by the HTML standard. The behavior without display:none is a bug according to it.

https://html.spec.whatwg.org/multipage/dom.html#the-innertext-idl-attribute:dom-innertext-3

Please use textContent or defaultValue or value setter instead of innerText setter.

说白了,早先 innerText 是 IE 自己搞的,现在已经进入到 HTML 标准中,而且定义了是会把 \n 变成 <br> 的,反倒是 没有 display:none 时,我们之前认为正确的结果是个 bug(我估计可能是为了不影响长久以来已经约定俗成的结果)。

备注:测试了一下 <pre> 效果与 <textarea> 完全一样。 

综上所述,面对未来的浏览器,更加严谨规范的操作 DOM,innerText 要根据你的场景来使用了,对于  <pre> 和 <textarea> 来说尽量使用 textContent / value 方法去操作吧。

展开阅读全文
打赏
0
0 收藏
分享
加载中
CodeMirror对滚动条的hack真心恶心。
2017/04/09 08:41
回复
举报
更多评论
打赏
1 评论
0 收藏
0
分享
返回顶部
顶部