关于vue中使用富文本tinymce使用,建议收藏

一:vue2.X版本 安装

@tinymce/tinymce-vue

  1. 网上查找安装版本
js 复制代码
 npm install tinymce@5.1.0 -S
 
 npm install @tinymce/tinymce-vue@3.0.1 -S
  1. 本人项目中使用版本
js 复制代码
"@tinymce/tinymce-vue": "^3.0.1",
"tinymce": "^5.10.2",

二:如何使用

  1. 把node_modules/tinymce下的skins 文件夹复制到public文件夹下
  2. 下载中文语言包 Language Packages | Trusted Rich Text Editor | TinyMCE 把解压后的中文语言包zh_CN.js复制到public文件夹下
  1. 在src/views/或者src/componets/你自己的相关文件夹内创建一个vue文件
  1. 文件内容 次文件内容可以直接复制使用
js 复制代码
<template>
	<div class="tinymce">
		<editor id="tinymce" v-model="Html" :init="tinymceInit" @input="echoEditor" />
		<!-- <div v-html="Html"></div> -->
	</div>
</template>

<script>
import uploadApi from "@/api/uploadApi/upload"
import tinymce from "tinymce/tinymce"
import "tinymce/themes/silver/theme"
import Editor from "@tinymce/tinymce-vue"
import "tinymce/icons/default/icons"
import "tinymce/plugins/image"
import "tinymce/plugins/link"
import "tinymce/plugins/code"
import "tinymce/plugins/table"
import "tinymce/plugins/lists"
import "tinymce/plugins/contextmenu"
import "tinymce/plugins/wordcount"
import "tinymce/plugins/colorpicker"
import "tinymce/plugins/textcolor"
import "tinymce/plugins/print"
import "tinymce/plugins/preview"
import "tinymce/plugins/searchreplace"
import "tinymce/plugins/autolink"
import "tinymce/plugins/directionality"
import "tinymce/plugins/visualblocks"
import "tinymce/plugins/visualchars"
import "tinymce/plugins/media"
import "tinymce/plugins/fullscreen"
import "tinymce/plugins/template"
import "tinymce/plugins/codesample"
import "tinymce/plugins/charmap"
import "tinymce/plugins/hr"
import "tinymce/plugins/pagebreak"
import "tinymce/plugins/nonbreaking"
import "tinymce/plugins/anchor"
import "tinymce/plugins/insertdatetime"
import "tinymce/plugins/advlist"
import "tinymce/plugins/lists"
import "tinymce/plugins/wordcount"
import "tinymce/plugins/imagetools"
import "tinymce/plugins/textpattern"
import "tinymce/plugins/help"
import "tinymce/plugins/emoticons"
import "tinymce/plugins/autosave"
import "tinymce/plugins/autoresize"
// import 'tinymce/baseURL/icons/custom'
// import '../../../public/tinymce/plugins/emoticons'
import "../../../public/tinymce/plugins/bdmap/plugin"
import "../../../public/tinymce/plugins/indent2em/plugin"
import "../../../public/tinymce/plugins/axupimgs/plugin"
// import 'tinymce/plugins/formatpainter'
function suffix(file) {
  const fileNameOne = file.name.lastIndexOf(".") // 取到文件名开始到最后一个点的长度
  const fileNameLength = file.name.length // 取到文件名长度
  const fileFormat = file.name.substring(fileNameOne + 1, fileNameLength) // 截去后缀名
  return fileFormat
}
export default {
  name: "NewTinymce",

  components: { Editor },
  props: {
    tinymceHtml: {
      type: String,
      default: ""
    },
    contentDetails: {
      type: String,
      default: ""
    }
  },
  data() {
    return {
      Html: "",
      tinymceInit: {
        language_url: "../../../tinymce/zh_CN.js",
        language: "zh_CN",
        skin_url: "../../../tinymce/skins/ui/oxide",
        emoticons_database_url: "../../../tinymce/plugins/emoticons/js/emojis.js",
        plugins:
          "print preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template code codesample table charmap hr pagebreak nonbreaking anchor insertdatetime advlist lists wordcount imagetools textpattern help emoticons autosave autoresize bdmap indent2em axupimgs",
        //     toolbar:
        //       'code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | \
        // styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
        // table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | bdmap indent2em lineheight axupimgs',
        toolbar: [
          // eslint-disable-next-line no-multi-str
          "code undo redo restoredraft | cut copy paste pastetext | forecolor backcolor bold italic underline strikethrough link anchor | alignleft aligncenter alignright alignjustify outdent indent | \
       styleselect formatselect fontselect fontsizeselect | bullist numlist | blockquote subscript superscript removeformat | \
         table image media charmap emoticons hr pagebreak insertdatetime print preview | fullscreen | bdmap indent2em lineheight axupimgs"
        ],
        height: 650, // 编辑器高度
        min_height: 400,
        // icons: 'custom',
        // inline: true,
        // statusbar: false,
        content_css: "../../../tinymce/skins/content/default/content.css", // 可设置编辑区内容展示的css,谨慎使用
        /* '/static/reset.css',
        '/static/ax.css',
        '/static/css.css',
    ],*/
        fontsize_formats: "12px 14px 16px 18px 24px 36px 48px 56px 72px",
        font_formats:
          "微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif;仿宋体=FangSong,serif;黑体=SimHei,sans-serif;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;",
        link_list: [
          { title: "预置链接1", value: "http://www.tinymce.com" },
          { title: "预置链接2", value: "http://tinymce.ax-z.cn" }
        ],
        image_list: [
          { title: "预置图片1", value: "https://www.tiny.cloud/images/glyph-tinymce@2x.png" },
          { title: "预置图片2", value: "https://www.baidu.com/img/bd_logo1.png" }
        ],
        image_class_list: [
          { title: "None", value: "" }
          // { title: 'Some class', value: 'class-name' }
        ],
        importcss_append: true,
        // 自定义文件选择器的回调内容
        file_picker_callback: function (callback, value, meta) {
          if (meta.filetype === "file") {
            // // 要先模拟出一个input用于上传本地文件
            var input = document.createElement("input")
            input.setAttribute("type", "file")
            // 你可以给input加accept属性来限制上传的文件类型
            // 例如:input.setAttribute('accept', '.jpg,.png')
            input.setAttribute("accept", ".doc,.docx,.ppt,.pptx,.pdf,.xlsx")

            input.onchange = function () {
              var file = this.files[0]
              let suffixY = ""
              if (suffix(file) === "doc" || suffix(file) === "docx") {
                suffixY = "msword"
              } else if (suffix(file) === "pdf") {
                suffixY = "pdf"
              } else if (suffix(file) === "json") {
                suffixY = "json"
              }
              uploadApi.getUpload({ bucketName: "notice", objectName: file.name }).then(res => {
                uploadApi.uploadFile({ url: res.data.uploadPath, file: file }, "application/" + suffixY).then(data => {
                  callback(res.data.downloadPath, { text: file.name })
                })
              })
            }
            input.click()
            // callback('https://www.baidu.com/img/bd_logo1.png', { text: 'My text' })
          }
          if (meta.filetype === "image") {
            // callback('https://www.baidu.com/img/bd_logo1.png', { alt: 'My alt text' })
            // 要先模拟出一个input用于上传本地文件
            // var input = document.createElement("input")
            input.setAttribute("type", "file")
            // 你可以给input加accept属性来限制上传的文件类型
            // 例如:input.setAttribute('accept', '.jpg,.png')
            input.setAttribute("accept", ".jpg,.png,.jpeg,.svg")
            input.onchange = function (e) {
              var file = this.files[0]
              let suffixY = ""
              if (suffix(file) === "png") {
                suffixY = "png"
              } else if (suffix(file) === "jpg") {
                suffixY = "jpeg"
              } else if (suffix(file) === "gif") {
                suffixY = "gif"
              }
              uploadApi.getUpload({ bucketName: "notice", objectName: file.name }).then(res => {
                uploadApi.uploadFile({ url: res.data.uploadPath, file: file }, "image/" + suffixY).then(data => {
                  callback(res.data.downloadPath, { text: file.name })
                })
              })
            }
            input.click()
          }
          if (meta.filetype === "media") {
            // callback('https://www.baidu.com/img/bd_logo1.png', { alt: 'My alt text' })
            // // 要先模拟出一个input用于上传本地文件
            // var input = document.createElement("input")
            input.setAttribute("type", "file")
            // 你可以给input加accept属性来限制上传的文件类型
            // 例如:input.setAttribute('accept', '.jpg,.png')
            input.setAttribute("accept", ".mp4,.mov,.wmv,.flv")
            input.click()
            input.onchange = function () {
              var file = this.files[0]
              uploadApi.getUpload({ bucketName: "notice", objectName: file.name }).then(res => {
                uploadApi.uploadFile({ url: res.data.uploadPath, file: file }).then(data => {
                  callback(res.data.downloadPath, { text: file.name })
                })
              })
            }
            // callback('movie.mp4', { source2: 'alt.ogg', poster: 'https://www.baidu.com/img/bd_logo1.png' })
          }
        },
        // 多图片上传在富文本内展示的路径(全路径时为空)
        images_upload_base_path: "",
        images_upload_handler: function (blobInfo, succFun, failFun) {
          var file = blobInfo.blob() // 转化为易于理解的file对象
          // // 要先模拟出一个input用于上传本地文件
          var input = document.createElement("input")
          input.setAttribute("type", "file")
          // 你可以给input加accept属性来限制上传的文件类型
          // 例如:input.setAttribute('accept', '.jpg,.png')
          let suffixY = ""
          if (suffix(file) === "png") {
            suffixY = "png"
          } else if (suffix(file) === "jpg") {
            suffixY = "jpeg"
          } else if (suffix(file) === "gif") {
            suffixY = "gif"
          }
          uploadApi.getUpload({ bucketName: "notice", objectName: file.name }).then(res => {
            uploadApi.uploadFile({ url: res.data.uploadPath, file: file }, "image/" + suffixY).then(data => {
              succFun(res.data.downloadPath)
            })
          })

          // callback('http
        },
        toolbar_sticky: true,
        autosave_ask_before_unload: false
      }
    }
  },
  watch: {
    tinymceHtml: {
      handler(val) {
        if (this.contentDetails) {
          this.Html = this.contentDetails + val
        } else {
          this.Html = val
        }
        this.$emit("echoEditor", this.Html)
      },
      immediate: true,
      deep: true
    },
    contentDetails: {
      handler(val) {
        this.Html = val
        this.$emit("echoEditor", this.Html)
      }
    }
  },
  mounted() {
    tinymce.init({})
  },
  methods: {
    echoEditor(data) {
      this.$store.commit("setHtml", data)
    }
    // echoEditor() {
    //   this.Html = tinymce.activeEditor.setContent();
    //   this.$store.commit("setHtml", this.Html)
    // }
  }
}
</script>
  1. 在需要的位置引入上面这个vue文件,作为子组件使用
  1. 页面展示

三:富文本tinymce获取实时输入数据看这篇文章

juejin.cn/spost/74288...

相关推荐
彭亚川Allen1 小时前
从零手搓 RAG 之文档解析技术
前端·后端·架构
oicola2 小时前
Ant Design v5 vs Tailwind CSS:组件库与样式框架的终极对决
前端·css
溪语流沙2 小时前
【Web全栈进阶】Vue Router + Pinia:SPA路由与全局状态
前端·javascript·vue.js
ManageEngineITSM2 小时前
工单优先级怎么定?影响×紧急度矩阵的设计与落地方法
java·大数据·运维·前端·数据库·变更管理
智商网输送线配件2 小时前
电子制造零散耗材补货实战:小批量混批采购平台怎么选才不停机?
大数据·服务器·前端·数据库·自动化
梦帮科技2 小时前
Web 漏洞攻防深度:WAF 规则逃逸技术(畸形分块传输、双重编码)与对抗加固
linux·前端·网络安全·ssl·web
兰亭妙微UI设计公司2 小时前
兰亭妙微软件界面设计公司的解锁按钮设计10大密码
开发语言·前端·javascript
迪幻2 小时前
封装自己的 npm 依赖并存储到个人 GitHub
前端·npm·github
u0111026753 小时前
WebP 转成 PNG 后为什么更大?图片格式转换不等于压缩
前端·javascript·vue.js
万少3 小时前
Qoder sonus模型 20分钟,复刻 马斯克 飞天汽车
前端·后端·算法