最近做項目有個富文本需求,選擇用vue-quill-editor,有些個性化設置,在這里記錄一下:
功能描述:點擊內容,展示富文本,保存后展示文本(如下圖):
編輯時候:

提交后變成查看狀態:

技術點有一下幾個:
1.toolbar個性化設置(字體大小設置item為自定義字體、自定義了一個工作匯報標簽,實現點擊展示彈窗效果)

實現方法主要是toolbar設置和樣式得處理:具體代碼入下:
toolbar設置:
//toolbarOptions配置
export const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'], // 加粗,傾斜,下划線,刪除線
['blockquote', 'code-block'], // 引號,代碼
[{ list: 'ordered' }, { list: 'bullet' }], // 有序列表,無序列表
[{ indent: '-1' }, { indent: '+1' }], // 左移,右移
[{ direction: 'rtl' }], // 左右對齊
[{ size: [false, '10px', '14px', '16px', '18px', '20px', '24px'] }], // 字體大小
[{ header: [1, 2, 3, 4, 5, false] }], // 標題大小
[{ color: [] }, { background: [] }], // 文字顏色,文字背景
[{ font: ['SimSun', 'SimHei', 'Microsoft-YaHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif'] }], // 字體風格
[{ align: [] }], // 對齊方式
['image', 'link', 'clean', 'report']// 圖片,鏈接,清除,自定義行為
]
//在quill中使用
toolbar: {
container: toolbarOptions,
handlers: {
report: this.openWorkReport
}
}
css配合(全部樣式,可以直接復制使用):
/* 字體風格 */
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='SimSun']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='SimSun']::before {
content: '宋體';
font-family: 'SimSun';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='SimHei']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='SimHei']::before {
content: '黑體';
font-family: 'SimHei';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='Microsoft-YaHei']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='Microsoft-YaHei']::before {
content: '微軟雅黑';
font-family: 'Microsoft YaHei';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='KaiTi']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='KaiTi']::before {
content: '楷體';
font-family: 'KaiTi';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='FangSong']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='FangSong']::before {
content: '仿宋';
font-family: 'FangSong';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='Arial']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='Arial']::before {
content: 'Arial';
font-family: 'Arial';
}
.ql-snow
.ql-picker.ql-font
.ql-picker-label[data-value='Times-New-Roman']::before,
.ql-snow
.ql-picker.ql-font
.ql-picker-item[data-value='Times-New-Roman']::before {
content: 'Times New Roman';
font-family: 'Times New Roman';
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='sans-serif']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='sans-serif']::before {
content: 'sans-serif';
font-family: 'sans-serif';
}
.ql-font-SimSun {
font-family: 'SimSun';
}
.ql-font-SimHei {
font-family: 'SimHei';
}
.ql-font-Microsoft-YaHei {
font-family: 'Microsoft YaHei';
}
.ql-font-KaiTi {
font-family: 'KaiTi';
}
.ql-font-FangSong {
font-family: 'FangSong';
}
.ql-font-Arial {
font-family: 'Arial';
}
.ql-font-Times-New-Roman {
font-family: 'Times New Roman';
}
.ql-font-sans-serif {
font-family: 'sans-serif';
}
/* 字體大小 */
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="false"]::before{
content: 'Normal';
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="10px"]::before{
content: '10px';
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="10px"]::before {
content: '10px';
font-size: 10px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="14px"]::before{
content: '14px';
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="14px"]::before {
content: '14px';
font-size: 14px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="16px"]::before{
content: '16px';
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="16px"]::before {
content: '16px';
font-size: 16px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="18px"]::before {
content: '18px';
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="18px"]::before {
content: '18px';
font-size: 18px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="20px"]::before{
content: '20px';
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="20px"]::before {
content: '20px';
font-size: 20px;
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="24px"]::before{
content: '24px';
}
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="24px"]::before {
content: '24px';
font-size: 24px;
}
/* 段落大小 */
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
content: '標題1';
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
content: '標題2';
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
content: '標題3';
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
content: '標題4';
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
content: '標題5';
}
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="false"]::before {
content: '正常';
}
/* 默認設置 */
.ql-snow .ql-editor{
font-size: 14px;
}
/* 查看樣式 */
.view-editor .ql-toolbar{
display: none;
}
.view-editor .ql-container.ql-snow{
border: 0;
}
.view-editor .ql-container.ql-snow .ql-editor{
padding: 0;
}
/* 編輯樣式 */
.edit-editor .ql-toolbar{
display: block;
}
.edit-editor .ql-container.ql-snow{
border: 1px solid #ccc;
min-height: inherit;
}
/* 自定義toobar樣式設計 */
/* 工作匯報彈窗 */
.ql-snow.ql-toolbar .ql-formats .ql-report{
background: url("../images/meeting/report.png") no-repeat;
background-size: contain;
display: inline-block;
height: 18px;
margin: 3px 5px;
width: 28px;
}
2.實現@或者#用戶功能,js實現代碼入下:
// 1.引入mention 組件
import mention from 'quill-mention'
//2.在quill potion配置入下:
// mentionList需要格式化為{id, value}形式
modules: {
mention: {
allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
source: (searchTerm, renderList) => {
renderList(this.mentionList, searchTerm)
},
onSelect: (data, insertItem) => {
insertItem(data)
this.onSelectd()
},
mentionDenotationChars: ['@', '#']
}
}
最后給出完整得vue配置:
<template>
<div @click="$emit('click')" :class="readonly?'view-editor':'edit-editor'" >
<quill-editor v-model="content"
:disabled="readonly"
:options="editorOption"
@change="onEditorChange($event)"
:style="{minHeight:readonly?'0':minHeigh+'px'}"
>
</quill-editor>
</div>
</template>
<script>
import Quill from 'quill'
import { quillEditor } from 'vue-quill-editor'
import { ImageDrop } from 'quill-image-drop-module'
import ImageResize from 'quill-image-resize-module'
import mention from 'quill-mention' // 引入mention 組件
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
import { fontSize, fonts, toolbarOptions } from './config'
Quill.register('modules/imageDrop', ImageDrop)
Quill.register('modules/imageResize', ImageResize)
Quill.register('modules/mention', mention)
const Size = Quill.import('attributors/style/size')
Size.whitelist = fontSize
Quill.register(Size, true)
const Font = Quill.import('formats/font')
Font.whitelist = fonts
Quill.register(Font, true)
export default {
name: 'index',
components: {
quillEditor
},
props: {
readonly: {
type: Boolean,
default: false
},
value: {
type: String,
default: ''
},
minHeigh: {
type: Number,
default: 200
},
isPushContent: {
type: Boolean,
default: false
},
mentionList: { // @功能
type: Array,
default: () => {
// 數據源(遍歷成{id, value}形式)
return []
}
}
},
data () {
return {
flag: true,
content: '',
editorOption: {
placeholder: '請輸入',
theme: 'snow',
modules: {
mention: {
allowedChars: /^[A-Za-z\sÅÄÖåäö]*$/,
source: (searchTerm, renderList) => {
renderList(this.mentionList, searchTerm)
},
onSelect: (data, insertItem) => {
// const item = { text: `@${data.value}`, name: data.value, id: data.id }
insertItem(data)
this.onSelectd()
},
mentionDenotationChars: ['@', '#']
},
imageDrop: true,
imageResize: {},
toolbar: {
container: toolbarOptions,
handlers: {
report: this.openWorkReport
}
}
}
},
replyTo: ''
}
},
watch: {
value: {
handler (val) {
this.content = val
},
immediate: true
}
},
methods: {
onSelectd () {
this.replyTo = this.mentionList
.reduce((acc, cur) => {
if (this.content.includes(cur.value)) {
acc.push(cur.id)
}
return acc
}, [])
.toString()
},
getEditorValue () {
return this.content
},
openWorkReport () {
this.$emit('openWorkReport')
},
setEditorValue (content = '') {
this.content = content
},
onEditorChange ({ quill, html, text }) {
this.content = html
this.$emit('input', this.content)
this.$emit('change', this.content)
}
}
}
</script>
<style>
@import '~@assets/css/font.css';
</style>
希望對你有用!
