富文本编辑器 vue-quill-editor入门(使用,显示,表格支持)

首先贴一下官方文档
http://doc.quilljs.cn/1409423
以及我参考的 很好的 一篇文章(在此表示感谢)
https://segmentfault.com/a/1190000019606714

然后是我的最终效果
在这里插入图片描述

其中红框1部分是插件自带的一下功能,我删除了一些不常用的(你们可以根据自己需要定制)
红框2部分是需要自己做的表格功能, 图标可以选择自己想用的svg

由于我不是专业前端,所以在项目中如何引入quill就不做赘述了,主要是提一些容易踩坑的点
先放一下代码 需要参考的大佬自取

略微注意一下
quill v1 版本不支持插入表格,v2的dev版本支持表格编辑。
npm install [email protected] -dev–save
(我没有做验证,但是挺多人这么说的,我就直接装了v2dev)

editor.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
<template>
  <keep-alive>
    <div>
      <div class="editor"></div>
    </div>
  </keep-alive>
</template>

<script>
import Quill from 'quill'
import 'quill/dist/quill.snow.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: Object
  },
  data () {
    return {
      quill: null,
      options: {
        theme: 'snow',
        modules: {
          toolbar: {
            container: [
              ['bold', 'italic', 'underline', 'strike'],
              [{ header: 1 }, { header: 2 }],
              [{ list: 'ordered' }, { list: 'bullet' }],
              [{ indent: '-1' }, { indent: '+1' }],
              [{ color: [] }, { background: [] }],
              [{ font: [] }],
              [{ align: [] }],
              ['clean'],
              [
                { 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(2, 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
        },
        placeholder: ''
      }
    }
  },
  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)
    this.quill.on('text-change', () => {
      //   console.log(this.quill.getContents())
      //   this.$emit('contentData', this.quill.getContents())
    //   console.log(this.quill.root.innerHTML)
      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>

需要引入editor的vue

1
2
3
<el-form-item label="内容">
            <editor v-model="content" @contentData="change($event)"></editor>
          </el-form-item>

需要展示editor的vue

1
2
3
4
5
<el-form-item label="内容">
            <div class="ql-container ql-snow">
              <div class="ql-editor" v-html="form.content"></div>
            </div>
          </el-form-item>

1.this.quill.root.innerHTML 可以获取富文本中的html格式内容,存入数据库后,在需要显示的地方取出,用v-html 展示。 (虽然目前官方不推荐使用)
2.在展示的时候需要class ql-container ql-snow 的div包裹起来,否则会丢失一些样式
3.this.quill.getContents() 取出的是Delta 格式的内容,我没有选择用这个办法。
4.quill 默认支持图片