18910140161

Vue的富文本插件(vue-quill-editor和tinymce)

顺晟科技

2022-09-13 11:10:27

183

一.使用vue-quill-editor实现富文本编辑器

Quill官方开发文档:https://www.kancloud.cn/liuwave/quill/1409423

1.安装依赖:npm install vue-quill-editor –save

2.在main.js或者需要用到此富文本的页面引入插件和Css:

       import { quillEditor } from "vue-quill-editor";        import "quill/dist/quill.core.css";        import "quill/dist/quill.snow.css";        import "quill/dist/quill.bubble.css"; 3.挂在组件:       export default { components: { quillEditor } } 4.自定义toolbar菜单      
      content: \'\', //富文本的内容
      editorOption: {
        modules: {
        toolbar: [
        [
        "bold",
         "italic",
        "underline",
        "strike",
        "link",
         "image",
         "code-block",
       ], // toggled buttons  
         [{ \'align\': [] }],    //对齐方式
        [{ \'header\': [1, 2, 3, 4, 5, 6, false] }],     //几级标题
         [{ \'font\': [] }],     //字体 
         [{ \'size\': [\'small\', \'normal\', \'large\', \'huge\'] }],
       [{ \'color\': [] }, { \'background\': [] }],     // 字体颜色,字体背景颜色 
         ],
       },
      },

 也可直接写editorOption:{},即会出现所有的工具栏

 5.在你想要用的位置用即可

<el-form-item label="内容:"
                      prop="content">
          <quill-editor ref="text"
                        v-model="content"
                        class="myQuillEditor"
                        :options="editorOption" />
        </el-form-item>

6.最终效果

 

 总的来说:vue-quill-editor还是比较简单的,用起来很方便,基本功能也有,一般的业务需求用这款富文本编辑器也还是比较合适的

                注:引入的Css样式,手机端无法解析,无法适配手机端样式,故如需适配手机端样式,还是不要用这个了!

                       我也是因为这个原因不得不换了其他富文本编辑器

                       我这里用到的是Tinymce

二:使用Tinymce实现富文本编辑器,功能更多,插件丰富,多语言支持

       中文文档:http://tinymce.ax-z.cn/

1.安装插件:npm install @tinymce/tinymce-vue@3.2.2 tinymce@5.3.1 -S

2.在项目中的public下新建tinymce文件夹,把node_modules中的skins文件夹,将skins文件夹拷贝到public的tinymce目录下。接着去官网下载语言包,解压,将langs文件夹拷贝到public的tinymce文件夹下(和skins文件夹同级)

3.在components文件夹下新建tinymce组件的文件夹,新建index.vue文件,复制以下代码进去:

<template>
 <div class="tinymce-editor">
  <Editor
   :id="editorId"
   v-model="editorValue"
   :init="editorInit"
  />
 </div>
</template>
 
<script>

//引入上传图片
import { getToken } from \'../../utils/auth\'
import axios from \'axios\'
// 引入组件
import tinymce from \'tinymce/tinymce\';
import Editor from \'@tinymce/tinymce-vue\';
import \'tinymce/icons/default/icons\';
import \'tinymce/themes/silver\';
// 引入富文本编辑器主题的js和css
import \'tinymce/themes/silver/theme.min\';
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\'; // 字数统计插件
import \'tinymce/plugins/media\';// 插入视频插件
import \'tinymce/plugins/template\';// 模板插件
import \'tinymce/plugins/fullscreen\';
import \'tinymce/plugins/paste\';
import \'tinymce/plugins/preview\';
import \'tinymce/plugins/contextmenu\';
import \'tinymce/plugins/textcolor\';

export default {
 name: \'TinymceEditor\',
 components: {Editor},
 props: {
  height: {
   type: Number,
   default: 500
  },
  id: {
   type: String,
   default: \'tinymceEditor\'
  },
  value: {
   type: String,
   default: \'\'
  },
  plugins: {
   type: [String, Array],
   default: \'link lists image code table wordcount media fullscreen preview paste contextmenu textcolor\'
  },
  toolbar: {
   type: [String, Array],
   default: \'fontselect| fontsizeselect | bold italic underline strikethrough table fullscreen  | link  image media  | undo redo  | alignleft aligncenter alignright alignjustify | bullist numlist | forecolor backcolor | outdent indent blockquote | code | removeformat\'
  }
 },
 data() {
  return {
   editorInit: {
    language_url: `/tinymce/langs/zh_CN.js`,
    language: \'zh_CN\',
    skin_url: `/tinymce/skins/ui/oxide`,
    content_css: `/tinymce/skins/content/default/content.css`,
    content_style: \'* { padding:0; margin:0; } img {max-width:100% !important }\',
    plugin_preview_width: 375, // 预览宽度
    plugin_preview_height: 200,
    lineheight_val: "1 1.1 1.2 1.3 1.35 1.4 1.5 1.55 1.6 1.75 1.8 1.9 1.95 2 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 3 3.1 3.2 3.3 3.4 4 5",
    fontsize_formats: "8pt 10pt 11pt 12pt 13pt 14pt 15pt 16pt 17pt 18pt 24pt 36pt",
    font_formats:"微软雅黑=\'微软雅黑\';宋体=\'宋体\';黑体=\'黑体\';仿宋=\'仿宋\';楷体=\'楷体\';隶书=\'隶书\';幼圆=\'幼圆\';Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings",
    plugins: this.plugins,
    powerpaste_word_import: \'merge\',
    toolbar: this.toolbar,
    height:400,
    media_live_embeds:true,//视频的内嵌代码预览是否开启,为ture时富文本编辑框可实现预览功能
    paste_data_images: true,
    statusbar: true, // 底部的状态栏
    menubar: false, // 最上方的菜单
    branding: false, // 水印“Powered by TinyMCE”
    images_upload_handler: (blobInfo, success, failure) => {
    //  this.$emit(\'handleImgUpload\', blobInfo, success, failure);
    this.handleImgUpload(blobInfo, success, failure)
    },
    //自定义逻辑替换 Tinymce 的默认媒体嵌入逻辑   
   },
   editorId: this.id,
   newValue: \'\'
  };
 },
 watch: {
  newValue(newValue) {
   this.$emit(\'input\', newValue);
  }
 },
 mounted() {
  tinymce.init({});
 },
 computed: {
  editorValue: {
   get() {
    return this.value;
   },
   set(val) {
    this.newValue = val;
   }
  }
 },
 methods: {
    // 上传本地 图片执行事件
    handleImgUpload(blobInfo, success, failure) {
      console.log(\'llllllllllllllllllllll\');
      let formdata = new FormData()
      // append 方法中的第一个参数就是 我们要上传文件 在后台接收的文件名
      // 这个值要根据后台来定义
      // 第二个参数是我们上传的文件
      formdata.append(\'file\', blobInfo.blob())
      // axios 定义上传方法
      axios({
        method: "post", // post方法
        url: "http://112.156.20.36:18000/manage/manage/file/uploadFile", // 请求上传图片服务器的路径
        headers: {
        \'Authorization\': \'Bearer \' + getToken(),\'Content-Type\': \'application/x-www-form-urlencoded\', // 采用表单上传的方式,看后台如何接受
        },
        data: formdata // 请求数据formdata
      }).then(res => {
        if (res.data.code != 200) {
          // 上传失败执行此方法,将失败信息填入参数中
          failure(\'HTTP Error: \' + res.msg);
          return
        }
        // 上传成功之后,将对应完整的图片路径拼接在success的参数中
        success(res.data.msg);
      })
    },
 
  clear() {
   this.editorValue = \'\';
  }
 }
};
</script>

图片上传,请是根据自己的实际情况做相应的更改

4.在你需要用到此富文本插件的页面引入插件,和挂载插件

  import TinymceEditor from \'@/components/tinymce\';

  components: { TinymceEditor},

5.在使用的位置使用即可

  <el-form-item label="内容:" prop="content">
              <tinymce-editor
              id="editor"
              ref="editor"
              v-model="formInline.content"
              style="width:60%;"
             />
        </el-form-item>

此刻,你不需要上传视频文件的需求等那么基本功能就可以实现了

如果,你要上传视频,就会出现视频无法预览的问题,此刻如果视频是内嵌视频代码地址,只需要

 media_live_embeds:true,//视频的内嵌代码预览是否开启,为ture时富文本编辑框可实现预览功能

如果不是内嵌视频,是普通视频的话,那就需要

1.打开node_modules->tinymce->plugins->media文件夹下的plugin.js文件作以下更改

  将此段代码注释

2.创建一个全局变量来存video的src 

3.在注释的代码下添加如下代码:

if(node.name === \'video\' && hasLiveEmbeds(editor) && global$8.ceFalse){
            console.log(\'videoSource===\', videoSource)
            videoSource = \'\'
            if(node.attributes[\'map\'] && node.attributes[\'map\'].src){
              videoSource = node.attributes[\'map\'].src
            }else{
              for(var ii=0;ii<node.attributes.length;ii++){
                if(node.attributes[ii].name == "src"){
                  videoSource = node.map.node.attributes[ii].value
                }
              }
            }
            if(node.firstChild && node.firstChild.value){
              var elel=node.firstChild && node.firstChild.value
              var objE = document.createElement("div");
             objE.innerHTML = elel;
              var dom = objE.getElementsByTagName(\'source\')[0]
              videoSource = dom.getAttribute(\'src\')
            }
            node.replace(createPreviewIframeNode(editor, node));
          }

4.修改此文件中createPreviewIframeNode方法(仅两处)

 var createPreviewIframeNode = function (editor, node) {
      var previewWrapper;
      var previewNode;
      var shimNode;
      var name = node.name;
      previewWrapper = new global$7(\'span\', 1);
      previewWrapper.attr({
        \'contentEditable\': \'false\',
        \'style\': node.attr(\'style\'),
        \'data-mce-object\': name,
        \'class\': \'mce-preview-object mce-object-\' + name
      });
      retainAttributesAndInnerHtml(editor, node, previewWrapper);
      previewNode = new global$7(name, 1);
      previewNode.attr({
        // src: node.attr(\'src\'),
        src: videoSource || node.attr(\'src\'), // 修改
        controls: \'controls\',    // 新增
        allowfullscreen: node.attr(\'allowfullscreen\'),
        style: node.attr(\'style\'),
        class: node.attr(\'class\'),
        width: node.attr(\'width\'),
        height: node.attr(\'height\'),
        frameborder: \'0\'
      });
      shimNode = new global$7(\'span\', 1);
      shimNode.attr(\'class\', \'mce-shim\');
      previewWrapper.append(previewNode);
      previewWrapper.append(shimNode);
      return previewWrapper;
    };

此时就显示正确了,内嵌视频和普通视频都可预览了,完美

 

参考文章:https://blog.csdn.net/Colourfuljia/article/details/108400662?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-5.not_use_machine_learn_pai&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-5.not_use_machine_learn_pai

 

 

我们已经准备好了,你呢?
2024我们与您携手共赢,为您的企业形象保驾护航