The whole process of using the rich text editor tinyMCE in vue2

Step 1: Install TinyMCE

$npm install [email protected] -S
$npm install @tinymce/[email protected] -S

Step 2: Find the tinymce folder in node_modules, move the internal files into the pubilc/tinymce folder, and introduce tinymce.min.js into the index.html file

Note: If you do not put the js file locally, the registration key prompt will be displayed when the rich text is displayed (you can also hide it with css yourself)

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="icon" href="<%= BASE_URL %>favicon.ico">
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
    </noscript>
    <div id="app">
      <script src="./tinymce/tinymce.min.js"></script>
    </div>
    <!-- built files will be auto injected -->
  </body>
</html>

Step Three: Chinese Language Pack

Create the file public/lang/zh_CN.js

Copy the following content directly into the file zh_CN.js

tinymce.addI18n('zh_CN',{
"Redo": "\重\做",
"Undo": "\撤\销",
"Cut": "\剪\切",
"Copy": "\复\制",
"Paste": "\粘\贴",
"Select all": "\全\选",
"New document": "\新\文\件",
"Ok": "\确\定",
"Cancel": "\取\消",
"Visual aids": "\网\格\线",
"Bold": "\粗\体",
"Italic": "\斜\体",
"Underline": "\下\划\线",
"Strikethrough": "\删\除\线",
"Superscript": "\上\标",
"Subscript": "\下\标",
"Clear formatting": "\清\除\格\式",
"Align left": "\左\边\对\齐",
"Align center": "\中\间\对\齐",
"Align right": "\右\边\对\齐",
"Justify": "\两\端\对\齐",
"Bullet list": "\项\目\符\号",
"Numbered list": "\编\号\列\表",
"Decrease indent": "\减\少\缩\进",
"Increase indent": "\增\加\缩\进",
"Close": "\关\闭",
"Formats": "\格\式",
"Your browser doesn't support direct access to the clipboard. Please use the Ctrl + \开\剪\贴\板\,\请\使\用Ctrl + X\/C\/V\等\快\捷\键\。",
"Headers": "\标\题",
"Header 1": "\标\题1",
"Header 2": "\标\题2",
"Header 3": "\标\题3",
"Header 4": "\标\题4",
"Header 5": "\标\题5",
"Header 6": "\标\题6",
"Headings": "\标\题",
"Heading 1": "\标\题1",
"Heading 2": "\标\题2",
"Heading 3": "\标\题3",
"Heading 4": "\标\题4",
"Heading 5": "\标\题5",
"Heading 6": "\标\题6",
"Preformatted": "\预\先\格\式\化\的",
"Div": "Div",
"Pre": "Pre",
"Code": "\代\码",
"Paragraph": "\段\落",
"Blockquote": "\引\文\区\块",
"Inline": "\文\本",
"Blocks": "\基\块",
"Paste is now in plain text mode. Contents will now be pasted as plain text until you toggle this option off.": "\当\前\为\纯\文\本\粘\贴\模\式\,\ u518d\次\点\击\可\以\回\到\普\通\粘\贴\模\式\。",
"Fonts": "\字\体",
"Font Sizes": "\字\号",
"Class": "\类\型",
"Browse for an image": "\浏\览\图\像",
"OR": "\或",
"Drop an image here": "\拖\放\一\张\图\像\至\此",
"Upload": "\上\传",
"Block": "\块",
"Align": "\对\齐",
"Default": "\默\认",
"Circle": "\空\心\圆",
"Disc": "\实\心\圆",
"Square": "\方\块",
"Lower Alpha": "\小\写\英\文\字\母",
"Lower Greek": "\小\写\希\腊\字\母",
"Lower Roman": "\小\写\罗\马\字\母",
"Upper Alpha": "\大\写\英\文\字\母",
"Upper Roman": "\大\写\罗\马\字\母",
"Anchor...": "\锚\点...",
"Name": "\名\称",
"Id": "\标\识\符",
"Id should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores.": "\标\识\符\应\该\以\字\母\开\头\,\后 ",
"You have unsaved changes are you sure you want to navigate away?": "\你\还\有\文\档\尚\未\保\存\,\确\定\要\离\开\?" ,
"Restore last draft": "\恢\复\上\次\的\草\稿",
"Special characters...": "\特\殊\字\符...",
"Source code": "\源\代\码",
"Insert\/Edit code sample": "\插\入\/\编\辑\代\码\示\例",
"Language": "\语\言",
"Code sample...": "\示\例\代\码...",
"Color Picker": "\选\色\器",
"R": "R",
"G": "G",
"B": "B",
"Left to right": "\从\左\到\右",
"Right to left": "\从\右\到\左",
"Emoticons...": "\表\情\符\号...",
"Metadata and Document Properties": "\元\数\据\和\文\档\属\性",
"Title": "\标\题",
"Keywords": "\关\键\词",
"Description": "\描\述",
"Robots": "\机\器\人",
"Author": "\作\者",
"Encoding": "\编\码",
"Fullscreen": "\全\屏",
"Action": "\操\作",
"Shortcut": "\快\捷\键",
"Help": "\帮\助",
"Address": "\地\址",
"Focus to menubar": "\移\动\焦\点\到\菜\单\栏",
"Focus to toolbar": "\移\动\焦\点\到\工\具\栏",
"Focus to element path": "\移\动\焦\点\到\元\素\路\径",
"Focus to contextual toolbar": "\移\动\焦\点\到\上\下\文\菜\单",
"Insert link (if link plugin activated)": "\插\入\链\接 (\如\果\链\接\插\件\已\激\活)",
"Save (if save plugin activated)": "\保\存(\如\果\保\存\插\件\已\激\活)",
"Find (if searchreplace plugin activated)": "\查\找(\如\果\查\找\替\换\插\件\已\激\活)",
"Plugins installed ({0}):": "\已\安\装\插\件 ({0}):",
"Premium plugins:": "\优\秀\插\件\:",
"Learn more...": "\了\解\更\多...",
"You are using {0}": "\你\正\在\使\用 {0}",
"Plugins": "\插\件",
"Handy Shortcuts": "\快\捷\键",
"Horizontal line": "\水\平\分\割\线",
"Insert\/edit image": "\插\入\/\编\辑\图\片",
"Image description": "\图\片\描\述",
"Source": "\地\址",
"Dimensions": "\大\小",
"Constrain proportions": "\保\持\纵\横\比",
"General": "\普\通",
"Advanced": "\高\级",
"Style": "\样\式",
"Vertical space": "\垂\直\边\距",
"Horizontal space": "\水\平\边\距",
"Border": "\边\框",
"Insert image": "\插\入\图\片",
"Image...": "\图\片...",
"Image list": "\图\片\列\表",
"Rotate counterclockwise": "\逆\时\针\旋\转",
"Rotate clockwise": "\顺\时\针\旋\转",
"Flip vertically": "\垂\直\翻\转",
"Flip horizontally": "\水\平\翻\转",
"Edit image": "\编\辑\图\片",
"Image options": "\图\片\选\项",
"Zoom in": "\放\大",
"Zoom out": "\缩\小",
"Crop": "\裁\剪",
"Resize": "\调\整\大\小",
"Orientation": "\方\向",
"Brightness": "\亮\度",
"Sharpen": "\锐\化",
"Contrast": "\对\比\度",
"Color levels": "\颜\色\层\次",
"Gamma": "\伽\马\值",
"Invert": "\反\转",
"Apply": "\应\用",
"Back": "\后\退",
"Insert date\/time": "\插\入\日\期\/\时\间",
"Date\/time": "\日\期\/\时\间",
"Insert\/Edit Link": "\插\入\/\编\辑\链\接",
"Insert\/edit link": "\插\入\/\编\辑\链\接",
"Text to display": "\显\示\文\字",
"Url": "\地\址",
"Open link in...": "\链\接\打\开\位\置...",
"Current window": "\当\前\窗\口",
"None": "\无",
"New window": "\在\新\窗\口\打\开",
"Remove link": "\删\除\链\接",
"Anchors": "\锚\点",
"Link...": "\链\接...",
"Paste or type a link": "\粘\贴\或\输\入\链\接",
"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?": "\你\所\填\写\的URL\地\址\为\邮\件\地\址 \,\需\要\加\上mailto:\前\缀\吗\?",
"The URL you entered seems to be an external link. Do you want to add the required http:\/\/ prefix?": "\你\所\填\写\的URL\地\址\属\于\外 \部\链\接\,\需\要\加\上http:\/\/:\前\缀\吗\?",
"Link list": "\链\接\列\表",
"Insert video": "\插\入\视\频",
"Insert\/edit video": "\插\入\/\编\辑\视\频",
"Insert\/edit media": "\插\入\/\编\辑\媒\体",
"Alternative source": "\镜\像",
"Alternative source URL": "\替\代\来\源\网\址",
"Media poster (Image URL)": "\封\面(\图\片\地\址)",
"Paste your embed code below:": "\将\内\嵌\代\码\粘\贴\在\下\面:",
"Embed": "\内\嵌",
"Media...": "\多\媒\体...",
"Nonbreaking space": "\不\间\断\空\格",
"Page break": "\分\页\符",
"Paste as text": "\粘\贴\为\文\本",
"Preview": "\预\览",
"Print...": "\打\印...",
"Save": "\保\存",
"Find": "\查\找",
"Replace with": "\替\换\为",
"Replace": "\替\换",
"Replace all": "\全\部\替\换",
"Previous": "\上\一\个",
"Next": "\下\一\个",
"Find and replace...": "\查\找\并\替\换...",
"Could not find the specified string.": "\未\找\到\搜\索\内\容.",
"Match case": "\区\分\大\小\写",
"Find whole words only": "\全\字\匹\配",
"Spell check": "\拼\写\检\查",
"Ignore": "\忽\略",
"Ignore all": "\全\部\忽\略",
"Finish": "\完\成",
"Add to Dictionary": "\添\加\到\字\典",
"Insert table": "\插\入\表\格",
"Table properties": "\表\格\属\性",
"Delete table": "\删\除\表\格",
"Cell": "\单\元\格",
"Row": "\行",
"Column": "\列",
"Cell properties": "\单\元\格\属\性",
"Merge cells": "\合\并\单\元\格",
"Split cell": "\拆\分\单\元\格",
"Insert row before": "\在\上\方\插\入",
"Insert row after": "\在\下\方\插\入",
"Delete row": "\删\除\行",
"Row properties": "\行\属\性",
"Cut row": "\剪\切\行",
"Copy row": "\复\制\行",
"Paste row before": "\粘\贴\到\上\方",
"Paste row after": "\粘\贴\到\下\方",
"Insert column before": "\在\左\侧\插\入",
"Insert column after": "\在\右\侧\插\入",
"Delete column": "\删\除\列",
"Cols": "\列",
"Rows": "\行",
"Width": "\宽",
"Height": "\高",
"Cell spacing": "\单\元\格\外\间\距",
"Cell padding": "\单\元\格\内\边\距",
"Show caption": "\显\示\标\题",
"Left": "\左\对\齐",
"Center": "\居\中",
"Right": "\右\对\齐",
"Cell type": "\单\元\格\类\型",
"Scope": "\范\围",
"Alignment": "\对\齐\方\式",
"H Align": "\水\平\对\齐",
"V Align": "\垂\直\对\齐",
"Top": "\顶\部\对\齐",
"Middle": "\垂\直\居\中",
"Bottom": "\底\部\对\齐",
"Header cell": "\表\头\单\元\格",
"Row group": "\行\组",
"Column group": "\列\组",
"Row type": "\行\类\型",
"Header": "\表\头",
"Body": "\表\体",
"Footer": "\表\尾",
"Border color": "\边\框\颜\色",
"Insert template...": "\插\入\模\板...",
"Templates": "\模\板",
"Template": "\模\板",
"Text color": "\文\字\颜\色",
"Background color": "\背\景\色",
"Custom...": "\自\定\义...",
"Custom color": "\自\定\义\颜\色",
"No color": "\无",
"Remove color": "\移\除\颜\色",
"Table of Contents": "\内\容\列\表",
"Show blocks": "\显\示\区\块\边\框",
"Show invisible characters": "\显\示\不\可\见\字\符",
"Word count": "\字\数",
"Words: {0}": "\字\数\:{0}",
"{0} words": "{0} \字",
"File": "\文\件",
"Edit": "\编\辑",
"Insert": "\插\入",
"View": "\视\图",
"Format": "\格\式",
"Table": "\表\格",
"Tools": "\工\具",
"Powered by {0}": "\由{0}\驱\动",
"Rich Text Area. Press ALT-F9 for menu. Press ALT-F10 for toolbar. Press ALT-0 for help": "\在\编\辑\区\按ALT-F9\打\开\菜\单\, \按ALT-F10\打\开\工\具\栏\,\按ALT-0\查\看\帮\助",
"Image title": "\图\片\标\题",
"Border width": "\边\框\宽\度",
"Border style": "\边\框\样\式",
"Error": "\错\误",
"Warn": "\警\告",
"Valid": "\有\效",
"To open the popup, press Shift + Enter": "\按Shitf + Enter\键\打\开\对\话\框",
"Rich Text Area. Press ALT-0 for help.": "\编\辑\区\。\按Alt + 0\键\打\开\帮\助\。",
"System Font": "\系\统\字\体",
"Failed to upload image: {0}": "\图\片\上\传\失\败: {0}",
"Failed to load plugin: {0} from url {1}": "\插\件\加\载\失\败: {0} \来\自\链\接 {1}",
"Failed to load plugin url: {0}": "\插\件\加\载\失\败 \链\接: {0}",
"Failed to initialize plugin: {0}": "\插\件\初\始\化\失\败: {0}",
"example": "\示\例",
"Search": "\搜\索",
"All": "\全\部",
"Currency": "\货\币",
"Text": "\文\字",
"Quotations": "\引\用",
"Mathematical": "\数\学",
"Extended Latin": "\拉\丁\语\扩\充",
"Symbols": "\符\号",
"Arrows": "\箭\头",
"User Defined": "\自\定\义",
"dollar sign": "\美\元\符\号",
"currency sign": "\货\币\符\号",
"euro-currency sign": "\欧\元\符\号",
"colon sign": "\冒\号",
"cruzeiro sign": "\克\鲁\赛\罗\币\符\号",
"french franc sign": "\法\郎\符\号",
"lira sign": "\里\拉\符\号",
"mill sign": "\密\尔\符\号",
"naira sign": "\奈\拉\符\号",
"peseta sign": "\比\塞\塔\符\号",
"rupee sign": "\卢\比\符\号",
"won sign": "\韩\元\符\号",
"new sheqel sign": "\新\谢\克\尔\符\号",
"dong sign": "\越\南\盾\符\号",
"kip sign": "\老\挝\基\普\符\号",
"tugrik sign": "\图\格\里\克\符\号",
"drachma sign": "\德\拉\克\马\符\号",
"german penny symbol": "\德\国\便\士\符\号",
"peso sign": "\比\索\符\号",
"guarani sign": "\瓜\拉\尼\符\号",
"austral sign": "\澳\元\符\号",
"hryvnia sign": "\格\里\夫\尼\亚\符\号",
"cedi sign": "\塞\地\符\号",
"livre tournois sign": "\里\弗\弗\尔\符\号",
"spesmilo sign": "spesmilo\符\号",
"tenge sign": "\坚\戈\符\号",
"indian rupee sign": "\印\度\卢\比",
"turkish lira sign": "\土\耳\其\里\拉",
"nordic mark sign": "\北\欧\马\克",
"manat sign": "\马\纳\特\符\号",
"ruble sign": "\卢\布\符\号",
"yen character": "\日\元\字\样",
"yuan character": "\人\民\币\元\字\样",
"yuan character, in hong kong and taiwan": "\元\字\样\(\港\台\地\区\)",
"yen\/yuan character variant one": "\元\字\样\(\大\写\)",
"Loading emoticons...": "\加\载\表\情\符\号...",
"Could not load emoticons": "\不\能\加\载\表\情\符\号",
"People": "\人\类",
"Animals and Nature": "\动\物\和\自\然",
"Food and Drink": "\食\物\和\饮\品",
"Activity": "\活\动",
"Travel and Places": "\旅\游\和\地\点",
"Objects": "\物\件",
"Flags": "\旗\帜",
"Characters": "\字\符",
"Characters (no spaces)": "\字\符(\无\空\格)",
"Error: Form submit field collision.": "\错\误: \表\单\提\交\字\段\冲\突\。",
"Error: No form element found.": "\错\误: \没\有\表\单\控\件\。",
"Update": "\更\新",
"Color swatch": "\颜\色\样\本",
"Turquoise": "\青\绿\色",
"Green": "\绿\色",
"Blue": "\蓝\色",
"Purple": "\紫\色",
"Navy Blue": "\海\军\蓝",
"Dark Turquoise": "\深\蓝\绿\色",
"Dark Green": "\深\绿\色",
"Medium Blue": "\中\蓝\色",
"Medium Purple": "\中\紫\色",
"Midnight Blue": "\深\蓝\色",
"Yellow": "\黄\色",
"Orange": "\橙\色",
"Red": "\红\色",
"Light Gray": "\浅\灰\色",
"Gray": "\灰\色",
"Dark Yellow": "\暗\黄\色",
"Dark Orange": "\深\橙\色",
"Dark Red": "\深\红\色",
"Medium Gray": "\中\灰\色",
"Dark Gray": "\深\灰\色",
"Black": "\黑\色",
"White": "\白\色",
"Switch to or from fullscreen mode": "\切\换\全\屏\模\式",
"Open help dialog": "\打\开\帮\助\对\话\框",
"history": "\历\史",
"styles": "\样\式",
"formatting": "\格\式\化",
"alignment": "\对\齐",
"indentation": "\缩\进",
"permanent pen": "\记\号\笔",
"comments": "\备\注",
"Anchor": "\锚\点",
"Special character": "\特\殊\符\号",
"Code sample": "\代\码\示\例",
"Color": "\颜\色",
"Emoticons": "\表\情",
"Document properties": "\文\档\属\性",
"Image": "\图\片",
"Insert link": "\插\入\链\接",
"Target": "\打\开\方\式",
"Link": "\链\接",
"Poster": "\封\面",
"Media": "\媒\体",
"Print": "\打\印",
"Prev": "\上\一\个",
"Find and replace": "\查\找\和\替\换",
"Whole words": "\全\字\匹\配",
"Spellcheck": "\拼\写\检\查",
"Caption": "\标\题",
"Insert template": "\插\入\模\板"
});

Step 4: Encapsulate the editor component in the src/components folder

Paste the code directly here

Notice:

  1. Because we need to set the header when uploading images, we customized the image upload images_upload_handler.
  2. If you encounter the problem that the video cannot be displayed on the display page after being inserted and saved, use a custom method to solve it.
<template>
<tiny-editor id="myEditor" ref="editorTools" v-model="content" :init="editorConfig"></tiny-editor>
</template>
<script>
// import { rootPath } from "@/utils/globalParam";
import Editor from "@tinymce/tinymce-vue"
import {
uploadImg
} from "@/api"
export default {
  components: {
      'tiny-editor': Editor
  },
  props: {
    modelValue: {
      type: String,
      default: ''
    }
  },
  data() {
      return {
        editorConfig: { // configuration
          selector: '#myEditor',
          branding: false,
          // inline: true,
          elementpath: false,
          height: 1100,
          menubar: 'my1',
          plugins: 'image link media table lists',
          // images_upload_url: rootPath + "/news/upload/file", // Image upload address
          images_upload_handler: function (blobInfo, succFun, failFun) {
              let fd = new FormData()
              fd.append('file', blobInfo.blob())
              fd.append('fileType', 'news.contentImage')
              uploadImg(fd).then(res => {
                succFun(res.relativePath)
              })
          },
           media_url_resolver: function(data, resolve) {
              try {
                  let embedHtml = ''
                  let videoUri = encodeURI(data.url);
                  if(data.url.indexOf('.mp4')>-1) {
                      // Determine whether it is mp4, otherwise use ifarme nesting
                      embedHtml = `<p>
                          <video src=${ data.url } width="100%" height="auto" style="max-width: 100%;" allowfullscreen="false" controls="controls" controlslist="nodownload">
                          </video>
                      </p>`;
                      resolve({ html: embedHtml });
                  }else {
                      embedHtml = `<p>
                      <iframe frameborder="0" src=${ data.url } width="100%" height="100%" style="max-width: 100%;">
                      </iframe>
                  </p>`;
              resolve({ html: embedHtml });
          }
          
      } catch (e) {
          resolve({ html: "" });
      }
  },
          menu: {
              my1: { title: '', items: ''},
          },
          language_url: "/tinymce/langs/zh_CN.js",
          language: "zh_CN",
          toolbar: "h1 h2 h3 | bold italic underline strikethrough | forecolor backcolor | bullist numlist alignleft aligncenter alignright alignjustify | outdent indent blockquote | undo redo removeformat | table link image media",
        },
        content: '',
      }
  },
  watch: {
    content(newValue) {
      this.$emit("input", newValue);
    },
  },
  created() {
    this.initData()
  },
  methods: {
    initData() {
      this.content = this.modelValue
    },
  }
}
</script>

Step 5: Reference the component’s parent page

<template>
    <tinymce-editor v-if='content' :model-value='content' @input='contentChange' />
</template>
<script>
import tinymceEditor from '@/components/editor.vue'
export default {
    components: {
        tinymceEditor: tinymceEditor
    },
    data() {
        content: ''
    },
    methods: {
        contentChange(data) {
            this.content = dats
        }
    }
}
</script>

Final display effect: