目前github上已經(jīng)有將Quill封裝一層的vue-quill-editor,對(duì)于使用Vue且想直接用Quill基本功能的同學(xué)剔宪,可以直接安裝使用宿饱。由于公司業(yè)務(wù)需要定制一些功能,用vue-quill-editor或直接用quill沒(méi)有太大區(qū)別针余,都需要自行封裝組件饲鄙,所以沒(méi)有引入vue-quill-editor,而是參考其封裝圆雁。
主要的props
- value: v-model綁定內(nèi)容
- toolbarOptions:指定工具欄功能項(xiàng)忍级,可以傳入數(shù)組,也可以傳入類(lèi)或id伪朽,如'.toolbar'轴咱。一開(kāi)始考慮用html的方式實(shí)現(xiàn)工具欄,以更靈活地進(jìn)行改寫(xiě)烈涮,綁定事件等朴肺。但這樣做,如果使用者想用組件已有幾種功能坚洽,也必須在外部重寫(xiě)toolbar的slot戈稿。最后選擇默認(rèn)使用options數(shù)組。
defaultToolbarOptions: [
['undo', 'redo'],
[{ 'size': this.sizeList }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
['blockquote', 'divider'],
['clean', 'formatBrush'],
['link', 'emoji', 'image'],
['bold', 'italic', 'underline', 'strike'],
[{ 'color': [] }, {'background': []}],
[{ 'script': 'sub' }, { 'script': 'super' }],
[{ 'indent': '-1' }, { 'indent': '+1' }, { 'align': [] }, { 'direction': 'rtl' }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }]
]
...
// 初始化
let toolbarOptions = this.toolbarOptions || this.defaultToolbarOptions
- options: 指定整個(gè)Quill初始化的options讶舰。用toolbarOptions可以滿(mǎn)足大部分業(yè)務(wù)器瘪,但不排除部分業(yè)務(wù)處理方法也需要定制,所以也應(yīng)該支持由外部來(lái)指定初始化的options绘雁。
- disabled: 是否可寫(xiě)
基礎(chǔ)文本模塊的封裝
一開(kāi)始考慮直接在組件中添加/重寫(xiě)模塊橡疼,分為以下4步:
- 組件引入格式類(lèi)
- 組件引入handler.js
- 統(tǒng)一增加對(duì)應(yīng)的工具欄圖標(biāo)
- 注冊(cè)引入的格式
- 綁定點(diǎn)擊工具欄圖標(biāo)的handler
···
// 1.引入對(duì)應(yīng)的格式類(lèi)
import Blockquote, {BlockquoteItem} from './editor-blot/blockquote.js'
import Divider from './editor-blot/divider.js'
// 2.引入handler
import {undo, redo, insertDivider, copyFormat} from './editor-blot/handler.js'
···
init () {
Quill.register('modules/imageResize', ImageResize)
// 3.圖標(biāo)增加
this.addIcons()
// 4.重寫(xiě)/添加格式功能
this.registerFormats()
this.options = {
modules: {
toolbar: {
container: this.$refs.toolbar,
// 5.改寫(xiě)handler
handlers: {
'undo': () => { undo(this.quill) },
'redo': () => { redo(this.quill) },
'divider': () => { insertDivider(this.quill) },
'formatBrush': () => { copyFormat(this.quill, this.copyFormatting) },
'emoji': function () {},
'image': () => {
this.img.show = true
}
}
},
imageResize: {},
toolbar_emoji: true,
short_name_emoji: true,
textarea_emoji: false,
tooltip: true
},
readOnly: this.readOnly,
placeholder: '請(qǐng)輸入內(nèi)容',
theme: 'snow'
}
this.quill = new Quill(this.$refs.editor, this.options)
},
/* 添加icons */
addIcons () {
let icons = Quill.import('ui/icons')
for (let key in ToolIcons) {
icons[key] = ToolIcons[key]
}
},
/* 注冊(cè)格式 */
registerFormats () {
// 字號(hào)重寫(xiě)
let Size = Quill.import('attributors/style/size')
Size.whitelist = ['12px', '14px', '16px', '18px', '20px', '24px']
Quill.register({
// 字號(hào)
'formats/size': Size,
// 段落
'formats/blockquote': Blockquote,
'formats/blockquote-item': BlockquoteItem,
// 分割線(xiàn)
'formats/divider': Divider
})
},
但這樣做,存在問(wèn)題:
- 如果使用者使用options屬性定制整個(gè)Quill庐舟,且又需要段落欣除、分割線(xiàn)等模塊,則需要將步驟1挪略,2, 4 , 5重復(fù)寫(xiě)一遍历帚。
- handler中需要傳入組件的this.quill,意味著在使用文件需要用this.
refs.quill來(lái)傳參杠娱,顯然這種方式不太友好挽牢。
為了解決這些問(wèn)題,最終決定參考github的其他Quill功能模塊(如quill-emoji)摊求,多一步封裝過(guò)程禽拔,合并格式類(lèi)和handler,將功能模塊化:
1.編寫(xiě)格式類(lèi)
2.編寫(xiě)模塊類(lèi),編寫(xiě)對(duì)應(yīng)的handler睹栖,并注冊(cè)到Quill的modules上(模塊對(duì)應(yīng)的index.js)
3.使用時(shí)硫惕,(組件/外部)直接引入模塊,并在options設(shè)置模塊為true
這樣一來(lái)野来,即便以后需要實(shí)現(xiàn)其他個(gè)性化業(yè)務(wù)恼除,使用者也能用步驟3,簡(jiǎn)單地引用已有模塊曼氛。如果需要新的模塊豁辉,可以編寫(xiě)后在組件引入。
...
// 引入模塊
import './quill-tooltip/tooltip-body.js'
import './quill-blockquote/index.js'
import './quill-divider/index.js'
import './quill-undo-redo/index.js'
import './quill-format-brush/index.js'
...
init () {
Quill.register('modules/imageResize', ImageResize)
this.addIcons()
this.registerFont()
let toolbarOptions = this.toolbarOptions || this.defaultToolbarOptions
this.defaultOptions = {
modules: {
toolbar: {
container: toolbarOptions,
handlers: {
'emoji': () => {},
'image': () => { this.img.show = true }
}
},
imageResize: {},
toolbar_emoji: true,
short_name_emoji: true,
textarea_emoji: false,
// 設(shè)置需要的模塊為true,從外部傳入模塊時(shí)舀患,直接設(shè)置即可
tooltip: true,
divider: true,
undo_redo: true,
format_brush: true
},
placeholder: '請(qǐng)輸入內(nèi)容',
theme: 'snow'
}
let options = this.options || this.defaultOptions
this.quill = new Quill(this.$refs.editor, options)
this.quill.enable(false)
this.initContent()
if (!this.disabled) {
this.quill.enable(true)
}
this.addEvents()
}