需求
(PC端)做一個可以使用圖片上傳、視訊上傳、檔案上傳功能的富文字元件,簡單的文字編輯釋出功能,採用socket方式傳輸,
做法
當時看到這個需求,我覺得是不難的,就去github上找富文字編輯器,因為專案比較急,當時我的想法是能找開箱即用的就找開箱即用的。
這幾個編輯器都試了一次,最後經過篩選
- Vue-Quill-Editor:不支援本地視訊上傳
- vue-froala-wysiwyg:我想要的功能都有包括圖片和視訊上傳,還額外支援響應式,但是是收費的
- ueditor:功能很全,但是樣式實在是很醜,可能要自己封裝
- 剩下的編輯器基本上要麼是功能不足或者是移動端的(優點是輕量)
因為沒做過富文字的開發,所以當時我測試這些富文字就花了一個下午,後來仔細考慮了一下,最後使用了比較保守的方式,用了ueditor開發,順便美化了一下。
引入ueditor
- import '../../static/UEditor/ueditor.config'
- import '../../static/UEditor/ueditor.all.min'
- import '../../static/UEditor/lang/zh-cn/zh-cn'
我們要去ueditor.config.js檔案裡面去改一下路徑配置
修改樣式
引入ueditor之後,直接讓工具欄隱藏起來,然後我們自己新建一個div模擬toolbars
隱藏之後的ueditor就是一個類似div加了可編輯屬性的既視感接下來我們直接一個div,然後給他一個flex佈局,然後去iconfont上面下載一些圖示,但是我們需要配置一下webpack使他支援批量處理svg,參考手摸手系列
現在就大變身了,樣子非常好看,跟現代的編輯器沒什麼差別給圖示繫結點選事件
經過上面的步驟,樣式基本上搞定了,剩下來就是使他們點選的時候,觸發事件,讓他們做出相應的動作就行,例如
execCommand: function (name) {
this.editor.execCommand(name)
},
複製程式碼
插入圖片,插入視訊,插入檔案這種操作,我並沒有使用ueditor內建的功能,視訊和資料夾我做成了進度條的形式,放在了富文字編輯器的下邊,圖片上傳成功後返回值拼接起來,根據雙向繫結,在editor元件內部動態建立圖片,點選這三個圖示,會把事件丟擲來,這樣你想用什麼上傳元件就用哪個,你還可以用socket進行上傳等等,這樣子,editor元件內部只需要維護編輯器的html文字就可以,職責單一,後期也好維護
editorData: {
body: '',
images: []
},
複製程式碼
本地儲存功能
最後新增了一個自動儲存的功能,這裡可以用定時器或者當內容發生變化的時候存到localStorage裡面。
autoSaveBody () {
if (this.isAutoSaved && this.editorData.body) {
let storage = {}
Object.assign(storage, this.editorData)
const pms = JSON.stringify(storage)
this.isAutoSaved = false
setTimeout(() => {
localStorage.setItem(this.storageKey, pms)
this.isAutoSaved = true
}, 500)
}
}
複製程式碼
但是必須要考慮一個情況,當前是第一次寫還是釋出之後進行修改,所以外部使用的時候,你只需要操作innerValue這個屬性,這個屬性的值你可以通過後臺來獲取(後臺獲取的就是修改狀態),然後編輯器就會呈現什麼樣的資料,內部的實現方式就是加了一個init函式
init: function () {
// 外部有預設值
if (this.value.body) {
this.editor.setContent(this.value.body)
} else {
// 有本地快取
const storage = localStorage.getItem(this.storageKey)
if (storage) {
const storageJson = JSON.parse(storage)
Object.assign(this.editorData, storageJson)
if (this.editorData.body) {
this.editor.setContent(this.editorData.body)
}
} else {
// 沒有本地快取
Object.assign(this.editorData, this.$options.data().editorData)
}
}
this.autoSaveInterval = setInterval(() => {
this.autoSaveBody()
}, 5000)
},
複製程式碼
缺點
元件太大,預設壓縮也有389k,開啟gzip之後有100k左右
優點
功能強大,產品需求可迭代。
補充
當然這個是我專案中抽取出來的,不是完整的程式碼,只是一個思路吧。第一次做富文字,要是說錯了大家多多指正,或者大家有更好的思路歡迎一起討論