要实现编辑器,首先div要实现可编辑状态,那么就需要用到 contenteditable。
contenteditable 属性规定元素内容是否可编辑。
注释:如果元素未设置 contenteditable 属性,那么元素会从其父元素继承该属性。
举个例子:
<blockquote contenteditable="true">
<p>Edit this content to add your own quote</p>
</blockquote>
该属性是一个枚举属性,而非布尔属性。这意味着必须显式设置其值为 true、false 或空字符串中的一个,并且不允许简写为 <label contenteditable>Example Label</label>,正确的用法是 <label contenteditable="true">Example Label</label>。
你可以使用CSS caret-color 属性设置用于绘制文本插入caret的颜色。
[contenteditable='true'] {
caret-color: #ff0000;
}
好了,实现编辑器最关键的一步已经了解,下面就开始吧。
搭建HTML基本结构:
<div
tabindex = "1"
:contenteditable="isContenteditable"
@dblclick = "onAllowEdit"
@blur = "onNoEdit">
<p :style="{
'text-align': item.textAlign,
'color': item.textColor,
'line-height': item.lineHeight + 'px',
'font-size': item.fontSize + 'px',
}">{{item.content}}</p>
</div>
div无法直接绑定 blur 事件,需要先使用 tabindex 将元素设置为 focusable 元素。
接下来一个重点知识点就来了,document.execCommand
当一个HTML文档切换到设计模式时,
document
暴露execCommand
方法,该方法允许运行命令来操纵可编辑内容区域的元素。
// 加粗
document.execCommand('bold', false, '')
// 超级链接
document.execCommand('createLink', false, 'https://www.baidu.com/')
这个时候你又会遇到一个坑,就是点击按钮的时候,div内的选区直接没了,无法进行设置,那么设置按钮需要使用以下2种:
- button
- a
API没有的功能就需要自己手写了,例如行高:
onTextFormat(type, value){
var that = this;
if(type == 'lineHeight'){
if(window.getSelection().rangeCount){
var range = window.getSelection().getRangeAt(0);
var contents = range.extractContents();
var span = document.createElement( 'span' );
span.style[type] = value;
span.appendChild(contents);
range.insertNode(span);
window.getSelection().removeAllRanges();
}
}else{
document.execCommand(type, false, value || '');
}
}
相关阅读:
https://segmentfault.com/q/1010000008495630
https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand
https://www.jianshu.com/p/f35fdb013c6f