如何使用 Vue 实现轻量级的富文本编辑器?

1. 引言

富文本编辑器是一个常见的需求,在网页中实现富文本编辑器通常使用的方法是通过引入富文本编辑器插件,例如 CKeditor 或 TinyMCE。但如果只需要实现简单的富文本编辑器,这些插件可能会过于臃肿。

本文将介绍如何使用 Vue 实现一个轻量级的富文本编辑器。

2. 实现思路

我们的富文本编辑器需要支持以下功能:

字体、字号、加粗、斜体、下划线、删除线、字体颜色、背景色、居中、左对齐、右对齐、编辑器全屏、清空内容、撤销、重做。

实现思路如下:

使用 contentEditable 属性实现可编辑区域。

使用 document.execCommand() 方法实现各种文本编辑操作。

使用 document.queryCommandState() 方法动态反映各种文本状态。

使用 CSS 样式实现各种文本样式。

3. HTML 结构

<template>

<div class="editor">

<div class="toolbar">

<button v-on:click="execCmd('bold')" :class="{ active: queryCmdState('bold') }">

<i class="fa fa-bold"></i>

</button>

<button v-on:click="execCmd('italic')" :class="{ active: queryCmdState('italic') }">

<i class="fa fa-italic"></i>

</button>

<button v-on:click="execCmd('underline')" :class="{ active: queryCmdState('underline') }">

<i class="fa fa-underline"></i>

</button>

<button v-on:click="execCmd('strikethrough')" :class="{ active: queryCmdState('strikethrough') }">

<i class="fa fa-strikethrough"></i>

</button>

<button v-on:click="execCmd('foreColor')">

<i class="fa fa-paint-brush"></i>

</button>

<button v-on:click="execCmd('backColor')">

<i class="fa fa-tint"></i>

</button>

<button v-on:click="execCmd('justifyLeft')" :class="{ active: queryCmdState('justifyLeft') }">

<i class="fa fa-align-left"></i>

</button>

<button v-on:click="execCmd('justifyCenter')" :class="{ active: queryCmdState('justifyCenter') }">

<i class="fa fa-align-center"></i>

</button>

<button v-on:click="execCmd('justifyRight')" :class="{ active: queryCmdState('justifyRight') }">

<i class="fa fa-align-right"></i>

</button>

<button v-on:click="fullscreen">

<i class="fa fa-expand-arrows-alt"></i>

</button>

<button v-on:click="clear">

<i class="fa fa-eraser"></i>

</button>

<button v-on:click="undo">

<i class="fa fa-undo"></i>

</button>

<button v-on:click="redo">

<i class="fa fa-redo"></i>

</button>

</div>

<div class="content">

<div class="text"></div>

</div>

</div>

</template>

3.1 解释

使用一个 div 元素作为编辑器容器,里面包含两个子元素:

.toolbar:工具栏,用于触发各种文本编辑操作。

.content:编辑器内容区域,即可编辑区域。

4. 样式

.editor {

border: 1px solid #ccc;

border-radius: 5px;

width: 100%;

height: 350px;

position: relative;

}

.toolbar {

background-color: #f5f5f5;

border-radius: 5px 5px 0 0;

position: absolute;

top: 0;

left: 0;

right: 0;

padding: 5px;

}

.toolbar button {

background-color: white;

border: none;

border-radius: 2px;

color: #666;

cursor: pointer;

font-size: 14px;

margin-right: 5px;

outline: none;

padding: 6px;

transition: all 0.1s ease-in-out;

}

.toolbar button:hover {

background-color: #f5f5f5;

color: #333;

}

.toolbar button.active {

background-color: #2e8b57;

color: white;

}

.content {

padding: 5px;

margin-top: 30px;

height: calc(100% - 30px);

overflow-y: auto;

}

.content .text {

font-size: 16px;

line-height: 1.5;

}

.fullscreen {

position: absolute;

top: 0;

right: 0;

}

.content-fullscreen {

position: fixed;

top: 0;

left: 0;

right: 0;

bottom: 0;

z-index: 9999;

background-color: white;

padding: 20px;

}

4.1 解释

.editor:编辑器容器。

.toolbar:工具栏。

.content:编辑器内容区域。

.toolbar button:工具栏按钮样式。

.content-fullscreen:全屏编辑器样式。

5. JavaScript 代码

<script>

export default {

data() {

return {

isFull: false,

elem: null

}

},

methods: {

execCmd(cmd, arg) {

document.execCommand(cmd, false, arg)

},

queryCmdState(cmd) {

return document.queryCommandState(cmd)

},

fullscreen() {

this.isFull = !this.isFull

if (this.isFull) {

this.elem = this.$el.querySelector('.content')

document.querySelector('body').classList.add('no-scroll')

this.elem.classList.add('content-fullscreen')

this.$el.querySelector('.content .text').setAttribute('contenteditable', false)

} else {

document.querySelector('body').classList.remove('no-scroll')

this.elem.classList.remove('content-fullscreen')

this.$el.querySelector('.content .text').setAttribute('contenteditable', true)

}

},

clear() {

if (confirm('确定要清空内容吗?')) {

this.$el.querySelector('.content .text').innerHTML = ''

}

},

undo() {

document.execCommand('undo', false, null)

},

redo() {

document.execCommand('redo', false, null)

}

}

}

</script>

5.1 解释

execCmd(cmd, arg):实现各种文本编辑操作。

queryCmdState(cmd):反映各种文本状态。

fullscreen():实现编辑器全屏,包括全屏样式和全屏状态的判断。

clear():实现清空内容,需要提示用户确认。

undo():实现撤销操作。

redo():实现重做操作。

6. 完成

以上代码就实现了一个简单的富文本编辑器。需要注意的是:

由于使用了 document.execCommand() 方法,因此兼容性可能会受到影响。

本编辑器样式可以根据需要进行修改。

7. 参考资料

https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand

https://developer.mozilla.org/en-US/docs/Web/API/Document/queryCommandState