運營同事在微信公衆號發佈文章時,經常按照如下步驟操做:html
打開「秀米」網 =》 挑選模版 =》 編輯好內容 =》 一鍵複製代碼vue
打開微信公衆平臺 =》 新建文章 =》 粘貼到編輯器裏 =》 確認發佈react
緊接着,這個工做多了一塊內容 —— 把內容同步到某個產品的觸屏網站中。jquery
因爲當下尚未資源開發一款相似「秀米」的產品,最終決定在以前的基礎上增長以下步驟:git
打開觸屏網站的內容管理平臺 =》 新建文章 =》 粘貼到編輯器裏 =》 確認發佈github
本來覺得只是像在微信公衆平臺同樣,在富文本編輯器裏粘貼便可,過程當中卻發現粘貼後部分樣式和標籤丟失微信
內容管理平臺中基於 Vue.js 開發,富文本編輯器使用的是 Quill。微信公衆平臺
而 Quill 簡潔易用的優勢,現在成了它的缺點 —— 它只保留特定的標籤和樣式,且沒有可供修改的配置。less
因而,決定選型其它富文本編輯器。編輯器
默認配置下和 Quill 問題同樣,而 Simditor 能夠經過配置來添加所需標籤和樣式。但有以下問題:
標籤須要手動一個個加進去,而樣式則須要針對每一個標籤分別添加。這種方案過程太費勁、容易遺漏
github 上大約是 2-3 年前的更新
依賴 jquery 實現
記得它早期版本依賴 jquery,在 github 上粗看了最新的代碼,3天前還在更新,已經無依賴,但兼容性要求 ie10 +。
注意到一個驚喜之處,他配套了 vue 和 react 相關的組件。
惋惜的是,它的問題和 Quill 同樣 —— 無法配置。
一些早期版本的富文本編輯器,基本上沒有對標籤和樣式的限制,但缺乏工程化支持
考慮到,無非是粘貼這麼一個簡單的需求,並且由於是內部系統,兼容性不是太大問題。
那麼,何苦費勁用功能那麼複雜的編輯器呢。
能夠經過事件對象來訪問黏貼板
event.clipboardData.getData('text/html')
MDN 上對 getData(format) 的惟一必填參數 format
的解釋,有點難理解
A DOMString representing the type of data to retrieve.
經過網上的一些例子,取值範圍大概能夠認爲等價於 MIME ,還包括 'Text'
、null
其實,解決了黏貼的問題,已經能夠告一段落了。
恰巧這時候查到了 contenteditable
相關資料,發現就是一個活脫脫的原生富文本編輯器。
<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>