碎碎念:在我为期2天的努力下终于把富文本封装弄好啦!参考了很多大佬的文章,写起来多多少少都有点问题,所以把这个文章整理出来给大家分享。希望帮助到大家。
主要参考(谢谢这位姐妹):vue使用quill富文本框添加表格功能_quill 表格-CSDN博客
1.quill
2.quill-better-table
3.要求:正常使用、可编辑、后台数据可回显
遇到的问题:
1.之前用的quill-editor 没办法回显表格样式所以替换成 quill和quill-better-table
⬇️
2.参考了上面姐妹的文章,后台数据不回显(可能是我写的有问题)
⬇️
3.后面在封装的富文本中watch监听的方法,可以正常回显啦
⬇️
4.但是在用到的组件中的这个方法 导致watch实时监听富文本中变化的数据,页面直接卡死。
⬇️
5.下面是最后实现的效果以及代码
富文本编辑器
实现步骤(vue2):
1.npm install quill@2.0.0-dev.4 --save
2.npm install --save quill-better-table
3.在components中封装一个editor.vue组件
<template>
<div>
<div class="editor"></div>
</div>
</template>
<script>
import Quill from 'quill'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.bubble.css'
const titleConfig = {
'ql-bold': '加粗',
'ql-color': '颜色',
'ql-font': '字体',
'ql-code': '插入代码',
'ql-italic': '斜体',
'ql-link': '添加链接',
'ql-background': '颜色',
'ql-size': '字体大小',
'ql-strike': '删除线',
'ql-script': '上标/下标',
'ql-underline': '下划线',
'ql-blockquote': '引用',
'ql-header': '标题',
'ql-indent': '缩进',
'ql-list': '列表',
'ql-align': '文本对齐',
'ql-direction': '文本方向',
'ql-code-block': '代码块',
'ql-formula': '公式',
'ql-image': '图片',
'ql-video': '视频',
'ql-clean': '清除字体样式',
'ql-upload': '文件',
'ql-table': '插入表格',
'ql-table-insert-row': '插入行',
'ql-table-insert-column': '插入列',
'ql-table-delete-row': '删除行',
'ql-table-delete-column': '删除列'
}
export default {
name: 'Editor',
props: {
value: {
type: String,
default: ''
}
},
data () {
return {
quill: null,
currentValue: '',
options: {
theme: 'snow',
modules: {
toolbar: {
container: [
['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
['blockquote', 'code-block'], // 引用 代码块
// [{ header: 1 }, { header: 2 }], // 1、2 级标题
[{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表
[{ script: 'sub' }, { script: 'super' }], // 上标/下标
[{ indent: '-1' }, { indent: '+1' }], // 缩进
// [{'direction': 'rtl'}], // 文本方向
[{ size: ['small', false, 'large', 'huge'] }], // 字体大小
[{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
[{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
[{ font: [] }], // 字体种类
[{ align: [] }], // 对齐方式
['clean'], // 清除文本格式
// ["link","image"], // 链接、图片、视频
[
{ table: 'TD' },
{ 'table-insert-row': 'TIR' },
{ 'table-insert-column': 'TIC' },
{ 'table-delete-row': 'TDR' },
{ 'table-delete-column': 'TDC' }
]
],
handlers: {
table: function (val) {
this.quill.getModule('table').insertTable(3, 3)
},
'table-insert-row': function () {
this.quill.getModule('table').insertRowBelow()
},
'table-insert-column': function () {
this.quill.getModule('table').insertColumnRight()
},
'table-delete-row': function () {
this.quill.getModule('table').deleteRow()
},
'table-delete-column': function () {
this.quill.getModule('table').deleteColumn()
}
}
},
table: true
},
// readOnly: true, //是否只读
placeholder: '请输入内容...'
}
}
},
watch: {
//这边是我第一次封装的时候写的
/* value: {
handler (val) {
if (val !== this.currentValue) {
this.currentValue = val === null ? '' : val
if (this.quill) {
this.quill.clipboard.dangerouslyPasteHTML(this.currentValue)
}
}
},
immediate: true
} */
},
methods: {
addQuillTitle () {
const oToolBar = document.querySelector('.ql-toolbar')
const aButton = oToolBar.querySelectorAll('button')
const aSelect = oToolBar.querySelectorAll('select')
aButton.forEach(function (item) {
if (item.className === 'ql-script') {
item.value === 'sub' ? (item.title = '下标') : (item.title = '上标')
} else if (item.className === 'ql-indent') {
item.value === '+1'
? (item.title = '向右缩进')
: (item.title = '向左缩进')
} else {
item.title = titleConfig[item.classList[0]]
}
})
aSelect.forEach(function (item) {
item.parentNode.title = titleConfig[item.classList[0]]
})
},
getContentData () {
return this.quill.getContents()
}
},
mounted () {
const dom = this.$el.querySelector('.editor')
this.quill = new Quill(dom, this.options)
// this.quill.setContents(this.value) //detla格式数据
// this.quill.setText(this.value) //纯文本
this.quill.clipboard.dangerouslyPasteHTML(0, this.value) // html格式数据
this.quill.on('text-change', () => {
// console.log(this.quill.getContents())//detla格式数据
// this.$emit('contentData', this.quill.getContents())
// console.log(this.quill.root.innerHTML)//html格式数据
this.$emit('contentData', this.quill.root.innerHTML)
})
this.$el.querySelector(
'.ql-table-insert-row'
).innerHTML = `<svg t="1591862376726" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6306" width="18" height="200"><path d="M500.8 604.779L267.307 371.392l-45.227 45.27 278.741 278.613L779.307 416.66l-45.248-45.248z" p-id="6307"></path></svg>`
this.$el.querySelector(
'.ql-table-insert-column'
).innerHTML = `<svg t="1591862238963" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6509" width="18" height="200"><path d="M593.450667 512.128L360.064 278.613333l45.290667-45.226666 278.613333 278.762666L405.333333 790.613333l-45.226666-45.269333z" p-id="6510"></path></svg>`
this.$el.querySelector(
'.ql-table-delete-row'
).innerHTML = `<svg t="1591862253524" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6632" width="18" height="200"><path d="M500.8 461.909333L267.306667 695.296l-45.226667-45.269333 278.741333-278.613334L779.306667 650.026667l-45.248 45.226666z" p-id="6633"></path></svg>`
this.$el.querySelector(
'.ql-table-delete-column'
).innerHTML = `<svg t="1591862261059" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6755" width="18" height="200"><path d="M641.28 278.613333l-45.226667-45.226666-278.634666 278.762666 278.613333 278.485334 45.248-45.269334-233.365333-233.237333z" p-id="6756"></path></svg>`
this.addQuillTitle()
},
activated () {
this.quill.setContents({})
}
}
</script>
4.在对应组件中使用
<template>
<div class="editor">
<MyEditor
ref="myQuillEditor"
class="editor"
v-model:value="ruleForm.contentString"
@contentData="onEditorChange1($event)"
>
</MyEditor>
</div>
</template>
<script>
import MyEditor from '@/components/KEditor/quillEditor.vue'
export default {
name: '',
props: {},
components: { MyEditor },
data () {
return {
ruleForm: {
contentString: ``,
}
},
methods: {
getdetial () {
if (this.$route.query.id) {
this.$bazaarApi
.getHzReportDetail({ id: this.$route.query.id })
.then(res => {
this.ruleForm = res.result
//这一步真的超级超级重要!!!!!
//在获取数据的接口里面写
this.$refs.myQuillEditor.quill.clipboard.dangerouslyPasteHTML(
res.result.contentString
)
})
}
}
},
//接收富文本编辑器中的数据
onEditorChange1 (val) {
this.ruleForm.contentString = val
}
},
mounted () {
this.getdetial()
},
watch: {},
computed: {},
filters: {}
}
</script>
<style scoped lang="scss">
</style>
结束啦!希望可以帮助到大家~