Vue背景管理システムリッチテキストコンポーネント(1)tinymce

Vue背景管理システムリッチテキストコンポーネント(1)tinymce

前書き

背景管理システムの最も重要な基本コンポーネントの1つとして、リッチテキストコンポーネントは、ピットの少ないリッチテキストメーカーから選択する必要があります。ここで使用されている小さなものはきれいで、穴が少なくなっています。

主に指示に依存します(最初にインストールし、手順は省略します)

 {
    
    
    "axios": "^0.18.0",
    "element-ui": "2.11.1",  
    "vue": "^2.6.10",    
    "vue-router": "^3.0.1"   
 }

tinymce:5.0.8ここでは、ソースコードのダウンロード方法を直接使用しています。Npmのダウンロードはパッケージング速度に大きく影響し、cdnも使用できます。

Tinymce公式ウェブサイトのダウンロードアドレス

テキスト

1.図に示すように、tinymceソースコードをダウンロードして、vue-cli3によって生成されたパブリックフォルダーの下の静的フォルダーに配置します。
ここに写真の説明を挿入

言語パックが必要な場合は、zh_CN.jsファイルを個別にダウンロードして、tinymce_5.0.8フォルダーの下のlangフォルダーに配置します。

zh_CN.js公式ウェブサイトダウンロードアドレス

2.エントリのhtmlファイルにインポートします


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="renderer" content="webkit" />
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"
    />
    <meta name="description" content="<%= webpackConfig.name %>" />
    <meta name="robots" content="noindex,nofollow,noarchive" /> 
    <title>title</title>
  </head>
  <body>
    <script src="<%= BASE_URL %>static/tinymce_5.0.8/tinymce.min.js"></script>  
    <div id="app"></div> 
  </body>
</html>

3.コンポーネントTinymce

ファイルディレクトリ

ここに写真の説明を挿入

src / components / Tinymce / index.vue

<template>
  <div class="tinymce-container editor-container" :class="{fullscreen:fullscreen}">
    <textarea :id="tinymceId" class="tinymce-textarea" />
    <div class="editor-custom-btn-container">
      <multiple-upload class="editor-upload-btn" @success="imageSuccess" />
    </div>
  </div>
</template>

<script>
import axios from 'axios'

 // MultipleUpload组件见 https://blog.csdn.net/qq_39953537/article/details/100039094

import MultipleUpload from '@/components/MultipleUpload'
import plugins from './plugins' // 见下文
import toolbar from './toolbar' // 见下文

// 上传html片段接口根据自己项目更换
import {
     
      uploadHtml } from '@/api/upload'
export default {
     
     
  name: 'Tinymce',
  components: {
     
     
    MultipleUpload
  },
  props: {
     
     
    // 默认填充到富文本的html文件
    html: {
     
     
      type: String,
      default: ''
    },
    toolbar: {
     
     
      type: Array,
      default() {
     
     
        return []
      }
    },
    menubar: {
     
     
      type: Boolean,
      default: false
    },
    height: {
     
     
      type: Number,
      default: 400
    }
  },
  data() {
     
     
    return {
     
     
      hasChange: false,
      hasInit: false,
      tinymceId: 'vue-tinymce-' + +new Date(),
      fullscreen: false,
      value: '',
      editorContent: ''
    }
  },
  watch: {
     
     
    value(val) {
     
     
      this.$nextTick(() =>
        window.tinymce.get(this.tinymceId).setContent(val || '')
      )
    },
    html(val) {
     
     
      if (this.isUrl) {
     
     
        this.loadUrl(val)
      }
    }
  },
  created() {
     
     
    if (this.html && this.html.startsWith('http')) {
     
     
      this.loadUrl(this.html)
    } else {
     
     
      this.value = this.html + ''
      this.editorContent = this.html + ''
    }
  },
  mounted() {
     
     
    this.initTinymce()
  },
  activated() {
     
     
    this.initTinymce()
  },
  deactivated() {
     
     
    this.destroyTinymce()
  },
  destroyed() {
     
     
    this.destroyTinymce()
  },
  methods: {
     
     
    initTinymce() {
     
     
      window.tinymce.init({
     
     
        fontsize_formats: '12px 14px 16px 18px 20px 24px 36px',
        language: 'zh_CN',
        language_url: '/static/tinymce_5.0.8/langs/zh_CN.js',
        selector: `#${
       
       this.tinymceId}`,
        height: this.height,
        body_class: 'panel-body ',
        object_resizing: true,
        toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
        menubar: this.menubar,
        plugins: plugins,
        end_container_on_empty_block: true,
        powerpaste_word_import: 'clean',
        code_dialog_height: 450,
        code_dialog_width: 1000,
        advlist_bullet_styles: 'square',
        advlist_number_styles: 'default',
        default_link_target: '_blank',
        link_title: false,
        init_instance_callback: editor => {
     
     
          if (this.value) {
     
     
            editor.setContent(this.value)
          }
          this.hasInit = true
          editor.on('NodeChange Change KeyUp SetContent', () => {
     
     
            this.hasChange = true
            this.$emit('input', editor.getContent())
            this.editorContent = editor.getContent()
          })
        },
        setup(editor) {
     
     
          editor.on('FullscreenStateChanged', e => {
     
     
            this.fullscreen = e.state
          })
        }
      })
    },
    destroyTinymce() {
     
     
      if (window.tinymce.get(this.tinymceId)) {
     
     
        window.tinymce.get(this.tinymceId).destroy()
      }
    },
    loadUrl(url) {
     
     
      if (url && url.length > 0) {
     
     
        axios
          .get(url)
          .then(response => {
     
     
            // 处理HTML显示
            this.value = response.data
            this.editorContent = response.data
            this.$emit('subLoadUrlToHtml', response.data)
            this.$emit('input', response.data)
          })
          .catch(() => {
     
     
            this.value = '服务器数据加载失败,请重试!'
          })
      }
    },
    // 设置编辑器内容
    setContent(value) {
     
     
      window.tinymce.get(this.tinymceId).setContent(value)
    },
    // 获取编辑器内容
    getContent() {
     
     
      window.tinymce.get(this.tinymceId).getContent()
    },
    // 图片上传成功后填充到富文本编辑器
    async imageSuccess(urlList) {
     
     
      try {
     
     
        let imageTemplateList = ''
        urlList.forEach(item => {
     
     
          const image = `<img style="max-width:100%;" src="${
       
       item}">`
          imageTemplateList = imageTemplateList + image
        })
        window.tinymce.get(this.tinymceId).insertContent(imageTemplateList)
        this.$message({
     
     
          message: '上传成功!',
          type: 'success'
        })
      } catch (error) {
     
     
        console.log(error)
        this.$message({
     
     
          message: error,
          type: 'error'
        })
      }
    },
    // 编辑器内容上传到cos,调用返回url
    async content2Url() {
     
     
      try {
     
     
        const res = await uploadHtml(this.editorContent)
        return res
      } catch (error) {
     
     
        this.$message({
     
     
          message: error.data.message,
          type: 'error'
        })
      }
    }
  }
}
</script>

<style lang='scss' >
#tinymce {
     
     
  background-color: blue;
  p {
     
     
    margin: 0;
  }
}
.tinymce-container {
     
     
  position: relative;
}
.tinymce-container >>> .mce-fullscreen {
     
     
  z-index: 10000;
}
.tinymce-textarea {
     
     
  visibility: hidden;
  z-index: -1;
}
.editor-custom-btn-container {
     
     
  position: absolute;
  right: 4px;
  top: 4px;
  /*z-index: 2005;*/
}
.fullscreen .editor-custom-btn-container {
     
     
  z-index: 10000;
  position: fixed;
}
.editor-upload-btn {
     
     
  display: inline-block;
}
// 隐藏底部logo栏
.mce-edit-area + .mce-statusbar {
     
     
  opacity: 0;
  height: 0;
}
</style>



src / components / Tinymce / plugins.js

const plugins = [
  'advlist anchor autolink autosave code codesample directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak  preview print save searchreplace spellchecker tabfocus table template  textpattern visualblocks visualchars wordcount paste'
]

export default plugins

src / components / Tinymce / toolbar.js

const toolbar = ['formatselect fontsizeselect forecolor backcolor bold italic underline strikethrough alignleft aligncenter alignright outdent indent    removeformat  hr undo redo']

export default toolbar

4.使用する

<template>
    <div>
        <tinymce
        ref="tinymce"
        :height="500"
        :html="html"
        @input="getContent"
        />
    </div>
</template>

<script>
import AppCropper from '@/components/Cropper'
export default {
     
     
  name: 'GoodsForm',
  components: {
     
     
    AppCropper
  },
  data() {
     
     
    return {
     
     
      html: 'https://ebusiness-1255313385.cosbj.myqcloud.com/image/20190823/center2019082304054532.html',
      content:''
    }
  },
  methods: {
     
     
      // 获取编辑器内容
    getContent(content) {
     
     
      this.content = content
    },
    // 编辑器内容转换成在线url
    async getcontent2Url() {
     
     
      try {
     
     
        const htmlUrl =  await this.$refs.tinymce.content2Url()
        return htmlUrl
      } catch (error) {
     
     
        console.log(error)
      }
    }

  }
}
</script>
 

5.使用効果
ここに写真の説明を挿入

参照リンク

1. https://github.com/PanJiaChen/vue-element-admin/blob/master/src/components/Tinymce/index.vue

2. TinyMCEの中国のドキュメント

おすすめ

転載: blog.csdn.net/qq_39953537/article/details/100041453