innerText 操作 textarea 的 “坑”

这两天正在把 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 方法去操作吧。

转载于:https://my.oschina.net/dyhunter/blog/868624

### 实现 Textarea 字数限制 为了在 Layui 框架中实现 `textarea` 输入框的字数限制功能,可以采用 HTML 和 JavaScript 结合的方式。HTML 部分用于定义输入区域以及显示当前已输入字符数量的位置;JavaScript 则负责监听用户的键盘操作并实时更新剩余可输入字符的数量。 #### HTML 代码结构 通过创建一个包含 `textarea` 的表单元素来接收用户输入,并放置一个小段文字用来动态展示已经输入了多少个字符: ```html <div class="layui-input-inline"> <textarea class="layui-textarea" id="reason" name="reason" maxlength="200" placeholder="请输入内容..." style="width:380px;margin-top:7px;height:75px;max-height:400px;overflow-x:auto;line-height:24px;" rows="3"></textarea> </div> <span id="wordsLength" style="position:absolute; right:-188px; bottom:-3vh;font-size:13px; color:#BDCADA">0/200</span> ``` 这段代码设置了最大允许输入长度为 200 个字符[^1]。 #### JavaScript 功能逻辑 为了避免因拼音输入法带来的问题,建议使用 `input` 或者 `propertychange` 事件代替传统的 `onkeyup` 来监控文本变化情况。每当检测到有新的输入时就计算现有字符串的实际长度,并相应调整提示信息中的数值。 ```javascript document.getElementById('reason').addEventListener('input', function () { var maxLength = this.getAttribute('maxlength'); var currentLength = this.value.length; document.getElementById('wordsLength').innerText = `${currentLength}/${maxLength}`; }); ``` 此脚本会在每次用户修改 `textarea` 中的内容之后立即执行,从而保持计数器与实际输入同步[^4]。 另外需要注意的是,在某些情况下(比如切换浏览器标签页后再返回),富文本编辑器内部的状态可能不会即时反映在外层的 `<textarea>` 上。因此,在提交之前应当调用一次显式的同步方法以确保最新数据被发送给服务器端处理[^3]。 对于更复杂的场景,如区分中英文字符的不同权重,则可以根据具体的业务需求编写额外的功能模块来进行判断和管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值