zoukankan      html  css  js  c++  java
  • 在vue cli 3脚手架里引入tinymce 5富文本编辑器

    本文主要讲的是在Vue cli 3脚手架搭建的项目里如何引用Tinymce 5富文本编辑器。

    请注意识别“版本号”,不同版本的配置细节有所不同。
    

    tinymce的安装

    安装tinymce-vue

    npm install @tinymce/tinymce-vue -S
    

    安装tinymce

    npm install tinymce -S
    

    下载中文语言包

    tinymce提供的语言包很多,选择下载中文语言包

    使用方法

    文件操作

    • 在项目根目录的public目录下新建tinymce文件夹,将下载的中文语言包解压后放在该文件夹下
    • 在依赖包node_modules里找到tinymce文件夹,将里面的skins文件夹复制到public/tinymce目录下

    目录截图

    tinymce初始化

    引入基本文件

    // 引入组件
    import tinymce from 'tinymce/tinymce'
    import Editor from '@tinymce/tinymce-vue'
    // 引入富文本编辑器主题的js和css
    import 'tinymce/themes/silver/theme.min.js'
    import 'tinymce/skins/ui/oxide/skin.min.css'
    // 扩展插件
    import 'tinymce/plugins/image'
    import 'tinymce/plugins/link'
    import 'tinymce/plugins/code'
    import 'tinymce/plugins/table'
    import 'tinymce/plugins/lists'
    import 'tinymce/plugins/wordcount'
    

    注册组件并使用

    注册组件

    components: { Editor }
    

    使用组件

    <Editor id="tinymce" v-model="tinymceHtml" :init="editorInit" />
    

    初始化配置项

    editorInit: {
        selector: '#tinymce',
        language_url: '/tinymce/langs/zh_CN.js',
        language: 'zh_CN',
        skin_url: '/tinymce/skins/ui/oxide',
        height: 300,
        plugins: 'link lists image code table wordcount',
        toolbar: 'bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat',
        images_upload_handler: (blobInfo, success, failure) => {
          this.handleImgUpload(blobInfo, success, failure)
        },
        statusbar: true // 底部的状态栏
        menubar: true, // 最上方的菜单
        branding: false // 水印“Powered by TinyMCE”
    }
    

    简单demo

    <template>
      <div class="activeConfig">
        <div class="activeConfig-container">
          <Editor id="tinymce" v-model="tinymceHtml" :init="editorInit" />
        </div>
      </div>
    </template>
    
    <script>
    // 引入组件
    import tinymce from 'tinymce/tinymce'
    import Editor from '@tinymce/tinymce-vue'
    // 引入富文本编辑器主题的js和css
    import 'tinymce/themes/silver/theme.min.js'
    import 'tinymce/skins/ui/oxide/skin.min.css'
    // 扩展插件
    import 'tinymce/plugins/image'
    import 'tinymce/plugins/link'
    import 'tinymce/plugins/code'
    import 'tinymce/plugins/table'
    import 'tinymce/plugins/lists'
    import 'tinymce/plugins/wordcount'
    // 引入api
    import { uploadImgage } from '@/api/activeConfig'
    
    export default {
      name: 'ActiveConfig',
      components: { Editor },
      data() {
        return {
          // tinymce的绑定值
          tinymceHtml: '',
          // tinymce的初始化配置
          editorInit: {
            selector: '#tinymce',
            language_url: '/tinymce/langs/zh_CN.js',
            language: 'zh_CN',
            skin_url: '/tinymce/skins/ui/oxide',
            height: 300,
            plugins: 'link lists image code table wordcount',
            toolbar: 'bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat',
            // 此处为图片上传处理函数
            images_upload_handler: (blobInfo, success, failure) => {
              this.handleImgUpload(blobInfo, success, failure)
            },
            statusbar: true // 底部的状态栏
            menubar: true, // 最上方的菜单
            branding: false // 水印“Powered by TinyMCE”
          }
        }
      },
      mounted() {
        tinymce.init({})
      },
      methods: {
        // 图片上传
        handleImgUpload(blobInfo, success, failure) {
          this.baseUrl = process.env.VUE_APP_BASE_URL
          const imgBase64 = `data:${blobInfo.blob().type};base64,${blobInfo.base64()}`
          const data = { img: [imgBase64] }
          uploadImgage(data).then(res => {
            // 传入success回调里的数据就是富文本编辑器里插入图片的src的值
            success(`${this.baseUrl}/${res.data[0]}`)
          }).catch(() => { failure('error') })
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .activeConfig {
      &-container {
        margin: 30px;
      }
    }
    </style>
    

    封装组件

    简单封装一下,方便使用

    <template>
      <div class="tinymce-editor">
        <Editor
          :id="editorId"
          v-model="editorValue"
          :init="editorInit"
          :disabled="disabled"
          @onClick="handleClick"
        />
      </div>
    </template>
    
    <script>
    // 引入组件
    import tinymce from 'tinymce/tinymce'
    import Editor from '@tinymce/tinymce-vue'
    // 引入富文本编辑器主题的js和css
    import 'tinymce/themes/silver/theme.min.js'
    import 'tinymce/skins/ui/oxide/skin.min.css'
    // 扩展插件
    import 'tinymce/plugins/image'
    import 'tinymce/plugins/link'
    import 'tinymce/plugins/code'
    import 'tinymce/plugins/table'
    import 'tinymce/plugins/lists'
    import 'tinymce/plugins/wordcount' // 字数统计插件
    
    export default {
      name: 'TinymceEditor'
      components: { Editor },
      props: {
        id: {
          type: String,
          default: 'tinymceEditor'
        },
        value: {
          type: String,
          default: ''
        },
        disabled: {
          type: Boolean,
          default: false
        },
        plugins: {
          type: [String, Array],
          default: 'link lists image code table wordcount'
        },
        toolbar: {
          type: [String, Array],
          default: 'bold italic underline strikethrough | fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist | outdent indent blockquote | undo redo | link unlink image code | removeformat'
        }
      },
      data() {
        return {
          editorInit: {
            language_url: '/tinymce/langs/zh_CN.js',
            language: 'zh_CN',
            skin_url: '/tinymce/skins/ui/oxide',
            height: 300,
            plugins: this.plugins,
            toolbar: this.toolbar,
            statusbar: true, // 底部的状态栏
            menubar: true, // 最上方的菜单
            branding: false, // 水印“Powered by TinyMCE”
            images_upload_handler: (blobInfo, success, failure) => {
              this.$emit('handleImgUpload', blobInfo, success, failure)
            }
          },
          editorId: this.id,
          editorValue: this.value
        }
      },
      watch: {
        editorValue(newValue) {
          this.$emit('input', newValue)
        }
      },
      mounted() {
        tinymce.init({})
      },
      methods: {
        // https://github.com/tinymce/tinymce-vue => All available events
        handleClick(e) {
          this.$emit('onClick', e, tinymce)
        },
        clear() {
          this.editorValue = ''
        }
      }
    }
    </script>
    
    

    封装组件后demo

    使用组件的完整demo示例

    <template>
      <div class="demo">
        <tinymce-editor
          :id="editorId"
          ref="editor"
          v-model="message"
          :disabled="isEditorDisabled"
          @input="handleInput"
          @onClick="handleClick"
          @handleImgUpload="imgUpload"
        />
        <div class="demo-btn">
          <el-button type="primary" @click="clearClick">清空内容</el-button>
          <el-button @click="disableClick">{{ !isEditorDisabled ? '禁用' : '启用' }}</el-button>
        </div>
      </div>
    </template>
    
    <script>
    import TinymceEditor from '@/components/TinymceEditor'
    
    export default {
      components: { TinymceEditor },
      data() {
        return {
          message: '我经常被生活锤得心灰意冷,可我从来都没放弃过。',
          editorId: 'editor-demo',
          isEditorDisabled: false
        }
      },
      methods: {
        // 输入事件
        handleInput(value) {
          console.log(value)
        },
        // 点击事件
        handleClick(e, editor) {
          console.log(e, editor)
        },
        // 上传图片
        imgUpload(blobInfo, success, failure) {
          const imgBase64 = `data:${blobInfo.blob().type};base64,${blobInfo.base64()}`
          success(imgBase64)
        },
        // 清空事件
        clearClick() {
          this.$refs.editor.clear()
        },
        // 禁用事件
        disableClick() {
          this.isEditorDisabled = !this.isEditorDisabled
        }
      }
    }
    </script>
    
    <style lang="scss" scoped>
    .demo {
      margin: 30px;
      &-btn {
        text-align: center;
        margin: 10px;
      }
    }
    </style>
    
    
  • 相关阅读:
    16. 3Sum Closest
    17. Letter Combinations of a Phone Number
    20. Valid Parentheses
    77. Combinations
    80. Remove Duplicates from Sorted Array II
    82. Remove Duplicates from Sorted List II
    88. Merge Sorted Array
    257. Binary Tree Paths
    225. Implement Stack using Queues
    113. Path Sum II
  • 原文地址:https://www.cnblogs.com/ykCoder/p/12106536.html
Copyright © 2011-2022 走看看