背景
运营同事在微信公众号发布文章时,常常按照以下步骤操作:
打开“秀米”网 =》 挑选模版 =》 编辑好内容 =》 一键复制代码
打开微信公众平台 =》 新建文章 =》 粘贴到编辑器里 =》 确认发布
紧接着,这个工作多了一块内容 —— 把内容同步到某个产品的触屏网站中。
由于当下还没有资源开发一款类似“秀米”的产品,最终决定在之前的基础上增加如下步骤:
打开触屏网站的内容管理平台 =》 新建文章 =》 粘贴到编辑器里 =》 确认发布
问题
原本以为只是像在微信公众平台一样,在富文本编辑器里粘贴即可,过程中却发现粘贴后部分样式和标签丢失
分析
Quill v1.3.0
内容管理平台中基于 Vue.js 开发,富文本编辑器使用的是 Quill。
而 Quill 简洁易用的优点,如今成了它的缺点 —— 它只保留特定的标签和样式,且没有可供修改的配置。
于是,决定选型其它富文本编辑器。
Simditor
默认配置下和 Quill 问题一样,而 Simditor 可以通过配置来添加所需标签和样式。但有如下问题:
标签需要手动一个个加进去,而样式则需要针对每个标签分别添加。这种方案过程太费劲、容易遗漏
github 上大约是 2-3 年前的更新
依赖 jquery 实现
wangeditor3
记得它早期版本依赖 jquery,在 github 上粗看了最新的代码,3天前还在更新,已经无依赖,但兼容性要求 ie10 +。
注意到一个惊喜之处,他配套了 vue 和 react 相关的组件。
可惜的是,它的问题和 Quill 一样 —— 没法配置。
其它
一些早期版本的富文本编辑器,基本上没有对标签和样式的限制,但缺少工程化支持
解决方案
考虑到,无非是粘贴这么一个简单的需求,而且因为是内部系统,兼容性不是太大问题。
那么,何苦费劲用功能那么复杂的编辑器呢。
clipboardData
可以通过事件对象来访问黏贴板
event.clipboardData.getData('text/html')
MDN 上对 getData(format) 的唯一必填参数 format
的解释,有点难理解
A DOMString representing the type of data to retrieve.
通过网上的一些例子,取值范围大概可以认为等价于 MIME ,还包括 'Text'
、null
一个神奇的属性 contenteditable
其实,解决了黏贴的问题,已经可以告一段落了。
恰巧这时候查到了 contenteditable
相关资料,发现就是一个活脱脱的原生富文本编辑器。
Vue 组件
<template>
<div class="ui-editor"
contenteditable="true"
@paste="paste"
@input="input"></div>
</template>
<script>
export default {
props: {
value: String
},
data() {
return {
html: ''
}
},
methods: {
paste(e) {
e.preventDefault()
const html = e.clipboardData.getData('text/html')
document.execCommand('insertHTML', false, html)
this.input()
},
input() {
const v = this.$el.innerHTML
this.html = v
this.$emit('input', v)
}
},
watch: {
value(v) {
if (v !== this.html) {
this.$el.innerHTML = v
}
}
},
mounted() {
const v = this.value
if (v) {
this.$el.innerHTML = v
this.html = v
}
}
}
</script>
<style lang="less">
.ui-editor {
margin: 10px auto;
width: 374px;
min-height: 300px;
padding: 0 15px;
box-shadow: inset 0 0 12px rgba(63, 70, 82, 0.5);
background-color: #fff;
overflow: hidden;
user-select: all;
&:hover {
outline: 1px solid red;
}
}
</style>
例子
<template>
<uEditor v-model="content" />
</template>
<script>
import uEditor from './editor.vue'
export default {
components: {
uEditor
},
data() {
return {
content:''
}
}
}
</script>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。