主要的思路是 div 标签的 user-modify 属性
user-modify 有以下属性:
- user-modify: read-only; (内容只读)
- user-modify: read-write;(内容可读写,支持富文本)
- user-modify: read-write-plaintext-only;(纯文本)
我们这边使用纯文本的就可以了
.input-box {
/* div 变成可编辑状态 */
-webkit-user-modify: read-write-plaintext-only;
border: 1px solid #000;
padding: 10px;
margin-bottom: 24px;
}
.input-box:hover {
outline: none;
}
接下来给两个标签,一个当作 textarea 一个用来触发行为;
<div>
<div class="input-box"></div>
<button id="btn">add a 标签</button>
</div>
js 代码核心的思路是:
- 拿到页面的鼠标位置;
- 监听光标的变化;
- 根据 id 对比拿到想要的 div,可以确保不会在其他位置插入;
- 通过
getRangeAt(0)方法拿到光标实例,执行上面的insertNode方法。
let saveRange = {}
function getRange () {
let sel = window.getSelection();
let range = sel.rangeCount > 0 ? sel.getRangeAt(0) : null;
if (range && range.commonAncestorContainer.ownerDocument.activeElement.id === 'breeze') {
saveRange = range
}
}
document.addEventListener('selectionchange', getRange) // 监听光标事件
let box = document.getElementsByClassName('input-box')[0];
box.id = 'breeze';
let btn = document.getElementById('btn');
btn.addEventListener('click', () => {
let node = document.createElement('a');
node.innerHTML = 'breeze';
node.href = 'wwww.baidu.com';
saveRange.deleteContents();
saveRange.insertNode(node);
})
这边介绍的方法是完全用原生的 js 写的,在框架中实现的思路是一样的,可以封装成一个比较通用的组件或者插件。