实现可文字编辑也可插入节点的功能
展示如下:

html5中contentEditable属性规定是否可编辑元素的内容,给需要编辑的节点添加contentEditable=“true”。
兼容性:

当点击Button时在编辑框内增加节点:

一开始div中加的span标签,发现有几个缺陷:

* 点删除键时span不会删除整个,而是一个一个删除span里的字符
* 当有连续的span时,光标会超出容器宽度在容器外面闪烁
针对以上第一个问题试了以下两种方法:

* <span contentEditable="false"></span>
* 设置css user-modify:设置css user-modify: read-only
两种方法都能解决无法删除整个节点的问题,但光标超出容器依然在╮( ̄▽  ̄)╭
各种翻找资料后找到一个解决办法:
加input节点,并且设置disabled
var inp = document.createElement("input"); inp.setAttribute("value", value);
inp.setAttribute("data-code", code); inp.setAttribute("disabled", 'true');
inp.style.width = this.input_resize(value) + 'px'; range.insertNode(inp);
input是不会自适应文本内容的,于是就有了input_resize去计算宽度,
input_resize(html) { inputResizeDom.innerHTML = html;
inputResizeDom.style.fontSize = '16px'; return
inputResizeDom.getBoundingClientRect().width.toFixed(4); }
方法是给另一个节点填充相同的内容,然后取这个节点的宽度作为input节点的宽度,需要注意的是,计算宽度的节点和 input的font-size与
font-family是相同的。

说到这个,不知道大家有木有注意到range.insertNode(inp)这么一句,他的作用是在存储的光标位置处添加节点,Range对象API
<https://developer.mozilla.org/en-US/docs/Web/API/Range>。
Range对象初始化:
//ie 9以下 var docSelection = document.selection; //chrome opera safari兼容 var
winSelection = window.getSelection; handleBlur() { if(!docSelection &&
winSelection){ sel = window.getSelection(); hasRange = sel.getRangeAt &&
sel.rangeCount; if(hasRange){ range = sel.getRangeAt(0);
range.deleteContents(); } } } handleKeyUp() { //ie获取光标定位 if(docSelection){
range = document.selection.createRange(); } },

为什么在ie浏览器下要在keyup触发方法中重置range,这就是有些坑了,chrome中blur事件触发时range记录光标在容器中的位置,但是在IE中记录的是blur时点击的元素(就是容器以外的元素),于是我在keyup事件中对range做一个存储。
顺便说一下,ie对onInput事件兼容性不是很好,慎重使用昂~。
点击按钮时触发操作:
selectLabel(value,code,event){ var target = event.currentTarget;
if(!$(target).hasClass('disabled')){ if(docSelection && document.selection.type
!= "Control"){ // IE9以下 let html = `<input value=${value} data-code=${code}
disabled="true" style="width: ${this.input_resize(value) + 'px'}"/>`
range.pasteHTML(html); }else if(winSelection && hasRange){ var inp =
document.createElement("input"); inp.setAttribute("value", value);
inp.setAttribute("data-code", code); inp.setAttribute("disabled", 'true');
inp.style.width = this.input_resize(value) + 'px'; range.insertNode(inp); }
$(target).addClass('disabled') this.setFocus($('#contentSms')) } }
几个用到的资料:
contentEditable API
<https://developer.mozilla.org/zh-CN/docs/Web/Guide/HTML/Content_Editable>
光标的使用 <https://www.jianshu.com/p/c85958c277b7>