vue-quill-editor的使用
最近做项目有个富文本需求,选择用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>
希望对你有用!

浙公网安备 33010602011771号