vue引用富文本编辑器tinymce

一 资源下载
tinymce 官方为vue项目提供了一个组件 tinymce-vue

1
npm install tinymce -S

我package.json文件里tinymce的版本是^4.8.5
安装之后,在 node_modules 中找到 tinymce/skins 目录,然后将 skins 目录拷贝到 static 目录下

// 如果是使用 vue-cli 3.x 构建的 typescript 项目,就放到 public 目录下,文中所有 static 目录相关都这样处理

tinymce 默认是英文界面,所以还需要下载一个中文语言包(记得搭梯子!搭梯子!搭梯子!)
下载中文语言包,附上地址中文包下载地址
然后将这个语言包放到 static 目录下,为了结构清晰,我包了一层 tinymce 目录
在这里插入图片描述
二 创建组件,在组件中引入以下文件
创建组件 tinymce-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
<template>
  <textarea :id='id' :value='value'></textarea>
</template>

<script>
// Import TinyMCE
import store from '@/store/store'
import tinymce from 'tinymce/tinymce'
import 'tinymce/skins/lightgray/skin.min.css'
import 'tinymce/themes/modern/theme'  //import 'tinymce/themes/silver/theme'
import 'tinymce/plugins/advlist'
import 'tinymce/plugins/link'
import 'tinymce/plugins/image'
import 'tinymce/plugins/code'
import 'tinymce/plugins/table'
import 'tinymce/plugins/textcolor'
import 'tinymce/plugins/paste'
import 'tinymce/plugins/colorpicker'
const INIT = 0
const CHANGED = 2
export default {
  data () {
    return {
      no: ''
    }
  },
  props: {
    value: {
      type: String,
      editor: null,
      required: true
    },
    setting: {},
    url: { // 接口
      default: '',
      type: String
    },
    accept: { // 文件类型
      default: 'image/jpeg, image/png',
      type: String
    },
    maxSize: { // 大小
      default: 2097152,
      type: Number
    },
    withCredentials: {
      default: false,
      type: Boolean
    }
  },
  watch: {
    value: function (val) {
      console.log('init ' + val)
      if (this.status === INIT || tinymce.activeEditor.getContent() !== val) {
        tinymce.activeEditor.setContent(val)
      }
      this.status = CHANGED
    }
  },
  data () {
    return {
      status: INIT,
      id: 'editor-' + new Date().getMilliseconds()
    }
  },
  methods: {
  },
  mounted () {
    const _this = this
    const setting =
        {
          selector: '#' + _this.id,
          images_upload_url: 'http://localhost:8080/uploadCenter/upload/images',
          language_url: '/tinymce/langs/zh_CN.js',
          language: 'zh_CN',
          init_instance_callback: function (editor) {
            // EDITOR = editor
            console.log('Editor: ' + editor.id + ' is now initialized.')
            editor.on('input change undo redo', () => {
              var content = editor.getContent()
              _this.$emit('show', content)
            })
          },
          content_style: `
    *                         { padding:0; margin:0; }
    html, body                { height:100%; }
    img                       { max-width:100%; display:block;height:auto; }
    a                         { text-decoration: none; }
    iframe                    { width: 100%; }
    p                         { line-height:1.6; margin: 0px; }
    table                     { word-wrap:break-word; word-break:break-all; max-width:100%; border:none; border-color:#999; }
    .mce-object-iframe        { width:100%; box-sizing:border-box; margin:0; padding:0; }
    ul,ol                     { list-style-position:inside; }
  `,
          insert_button_items: 'image link | inserttable',
          paste_retain_style_properties: 'all',
          paste_word_valid_elements: '*[*]', // word需要它
          paste_data_images: true, // 粘贴的同时能把内容里的图片自动上传,非常强力的功能
          paste_convert_word_fake_lists: false, // 插入word文档需要该属性
          paste_webkit_styles: 'all',
          paste_merge_formats: true,
          nonbreaking_force_tab: false,
          paste_auto_cleanup_on_paste: false,
          menubar: 'edit insert view format table tools',
          branding: false,
          plugins: [
            'advlist autolink lists image charmap print preview hr anchor pagebreak imagetools',
            'searchreplace visualblocks visualchars code  fullpage',
            'insertdatetime nonbreaking save table contextmenu directionality',
            'emoticons paste textcolor colorpicker textpattern imagetools'
          ],
          toolbar1: ' newnote print fullscreen preview | undo redo | insert | styleselect | forecolor backcolor bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image emoticons media codesample',
          // 上传图片回调
          images_upload_handler (blobInfo, success, failure) {
            let xhr = ''
            let formData = ''
            xhr = new XMLHttpRequest()
            xhr.withCredentials = false
            xhr.open('POST', 'http://localhost:8080/uploadCenter/upload/images')
            xhr.setRequestHeader('token','')
            xhr.onload = () => {
              let json = {}
              if (xhr.status !== 200) {
                failure('HTTP Error: ', xhr.status)
                return
              }
              console.log(xhr)
              json = JSON.parse(xhr.responseText)
              console.log(json)
              success(json.data.httpFilePath)
            }
            formData = new FormData()
            formData.append('file', blobInfo.blob())
            xhr.send(formData)
          }
        }
    Object.assign(setting, _this.setting)
    tinymce.init(setting)
  },
  beforeDestroy: function () {
    tinymce.get(this.id).destroy()
  }
}
</script>

三 其他组件引用

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
<template>
 <div class="app-container calendar-list-container">
   <div style="width: 100%;">
     <editor class="editor" :value="content" :setting="editorSetting" @show="editors" :with-credentials="withCredentials"></editor>
   </div>
 </div>
</template>

<script>
import editor from './tinymce-editor' // 根据tinymce-editor.vue组件位置引入
export default {
  data () {
    return {
      editorSetting: { // 配置富文本编辑器高
        height: 500
      },
      withCredentials: true,
      content: '', // 富文本编辑器双向绑定的内容
      formLeft: {
        title: ''
      }
    }
  },
  components: { // 引入组件
    editor
  },
  methods: {
    editors (content) { // editor组件传过来的值赋给content
      console.log(content)
      this.content = content
    }
  }
}
</script>