前言


需求需要实现富文本的功能,同时富文本中还可以上传视频和图片,选来选去最后决定了用这个富文本编辑器

官网:https://quilljs.com/

1、安装富文本编辑器

npm install vue-quill-editor --save

2、在main.js中引入

import VueQuillEditor from 'vue-quill-editor'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
Vue.use(VueQuillEditor);

3、在页面中的使用

(1)template中使用
 <div class="edit_container" style="width: 100%;height: 100%">
      <quill-editor
        v-model="content"
        ref="myQuillEditor"
        :options="editorOption"
        @blur="onEditorBlur($event)" @focus="onEditorFocus($event)"
        @change="onEditorChange($event)">
      </quill-editor>
      <!-- 使用input 标签劫持原本视频上传事件,实现视频上传 -->
      <input type="file" accept="video/*" name="file" ref="uploadFileVideo" id="uploadFileVideo" @change="changevideo" style="opacity: 0; width: 0; height: 0;cursor: pointer">
      <!--使用input 标签劫持原本图片上传事件,实现图片上传-->
      <input type="file" name="file" id="uploadFileImg" ref="uploadFileImg" @change="changeImg" style="opacity: 0; width: 0; height: 0;cursor: pointer">
    </div>
(2)script 中引入
  import * as Quill from 'quill';  //引入编辑器
  //自定义quill编辑器的字体
  var fonts = ['Microsoft-YaHei', 'YouYuan',  'SimSun', 'SimHei', 'KaiTi', 'FangSong', 'Arial', 'Times-New-Roman', 'sans-serif'];
  var Font = Quill.import('formats/font');
  Font.whitelist = fonts; //将字体加入到白名单
  Quill.register(Font, true);
  /*设置字体大小*/
  var Size = Quill.import('attributors/style/size');
  Size.whitelist = ['10px', '12px', '14px', '16px', '18px', '20px', '24px', false];
  Quill.register(Size, true);
(3)data 中定义
editorOption: {
         placeholder: '输入文本...',
         theme: 'snow', //主题
         modules: {
           imageResize: {   //添加图片拖拽上传,自定义大小(下面会详细介绍安装方法)
             displayStyles: {   //添加
               backgroundColor: 'black',
               border: 'none',
               color: 'white'
             },
             modules: ['Resize', 'DisplaySize', 'Toolbar']   //添加
           },
           toolbar: {
             container: [
               ['bold', 'italic', 'underline', 'strike'],    //加粗,斜体,下划线,删除线
               ['blockquote', 'code-block'],     //引用,代码块
               [{ 'header': 1 }, { 'header': 2 }],        // 标题,键值对的形式;1、2表示字体大小
               [{'list': 'ordered'}, { 'list': 'bullet' }],     //列表
               [{'script': 'sub'}, { 'script': 'super' }],   // 上下标
               [{'indent': '-1'}, { 'indent': '+1' }],     // 缩进
               [{ 'direction': 'rtl' }],             // 文本方向
               [{ 'size': ['10px', '12px', '14px', '16px', '18px', '20px', '24px', false] }], // 字体大小,false设置自定义大小
               [{ 'header': [1, 2, 3, 4, 5, 6, false] }],     //几级标题
               [{ 'color': [] }, { 'background': [] }],     // 字体颜色,字体背景颜色
               [{ 'font': fonts }],     //字体
               [{ 'align': [] }],    //对齐方式
               ['clean'],    //清除字体样式
               ['image', 'video']    //上传图片、上传视频
             ],
             handlers: {
               'video': function(val) {// 劫持原来的视频点击按钮事件
                 document.querySelector('#uploadFileVideo').click();
               },
               'image': function () {  // 劫持原来的图片点击按钮事件
                 document.querySelector('#uploadFileImg').click();
               }
             }
           }
         }
       }
(5)methods 中的方法
   methods: {
      getMountData() {},
      onEditorReady(editor) {},// 准备编辑器
      onEditorBlur() {}, // 失去焦点事件
      onEditorFocus() {}, // 获得焦点事件
      onEditorChange() {}, // 内容改变事件
      // 转码
      escapeStringHTML(str) {
        str = str.replace(/&lt;/g, '<');
        str = str.replace(/&gt;/g, '>');
        return str;
      },
      changeImg() {
        //上传图片到服务器
        //回调中调用  this.insertEle('image', data); 方法,插入图片到富文本
      }, //图片上传事件
      changevideo() {
          //上传视频到服务器
        //回调中调用  this.insertEle('video', data); 方法,插入图片到富文本
      },  //视频上传事件
      insertEle(type, url) {
          let quill = this.$refs.myQuillEditor.quill;
          let length = quill.getSelection().index;
          // 插入视频  response.data.url为服务器返回的图片地址
          if (type === 'video') {
            quill.insertEmbed(length, 'simpleVideo', {
              url,
              controls: 'controls',
              width: '100%',
              height: 'auto'
            });
          } else {
            quill.insertEmbed(length, type, url);
          }
          // 调整光标到最后
          quill.setSelection(length + 1);
        }
    }
(6)css 部分
  .ql-snow .ql-picker.ql-header .ql-picker-item::before {
    content: '文本';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
    content: '标题1';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
    content: '标题2';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
    content: '标题3';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
    content: '标题4';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
    content: '标题5';
  }
  .ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
  .ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
    content: '标题6';
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimSun]::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimSun]::before {
    content: "宋体";
    font-family: "SimSun";
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
    content: "黑体";
    font-family: "SimHei";
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
    content: "微软雅黑";
    font-family: "Microsoft YaHei";
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=YouYuan]::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=YouYuan]::before {
    content: "幼圆";
    font-family: "YouYuan";
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
    content: "楷体";
    font-family: "KaiTi";
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
    content: "仿宋";
    font-family: "FangSong";
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
    content: "Arial";
    font-family: "Arial";
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
    content: "Times New Roman";
    font-family: "Times New Roman";
  }
  .ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
  .ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
    content: "sans-serif";
    font-family: "sans-serif";
  }

  .ql-font-SimSun {
    font-family: "SimSun";
  }
  .ql-font-SimHei {
    font-family: "SimHei";
  }
  .ql-font-YouYuan {
    font-family: "YouYuan";
  }
  .ql-font-Microsoft-YaHei {
    font-family: "Microsoft YaHei";
  }
  .ql-font-KaiTi {
    font-family: "KaiTi";
  }
  .ql-font-FangSong {
    font-family: "FangSong";
  }
  .ql-font-Arial {
    font-family: "Arial";
  }
  .ql-font-Times-New-Roman {
    font-family: "Times New Roman";
  }
  .ql-font-sans-serif {
    font-family: "sans-serif";
  }
  /*字体样式*/
  /*//默认的样式*/
  .ql-container {
    font-size:16px;
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='10px']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='10px']::before {
    content: '10px';
    font-size: 10px;
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='12px']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='12px']::before {
    content: '12px';
    font-size: 12px;
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='14px']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='14px']::before {
    content: '14px';
    font-size: 14px;
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='16px']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='16px']::before {
    content: '16px';
    font-size: 16px;
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='18px']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='18px']::before {
    content: '18px';
    font-size: 18px;
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='20px']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='20px']::before {
    content: '20px';
    font-size: 20px;
  }
  .ql-snow .ql-picker.ql-size .ql-picker-label[data-value='24px']::before,
  .ql-snow .ql-picker.ql-size .ql-picker-item[data-value='24px']::before {
    content: '24px';
    font-size: 24px;
  }
  //自己添加自己需要的字体和样式

4、quill-image-resize-module的安装和使用

这个是quill的一个组件,可以对上传到富文本的图片进行调整,实用又方便。

(1)安装 quill-image-resize-module

npm install quill-image-resize-module --save

(2) script 引入
import ImageResize from 'quill-image-resize-module'  //添加
Quill.register('modules/imageResize', ImageResize)  //添加
(3) 配置editorOption.modules{}中添加以下代码(上面editorOption)为已经配置好的
  imageResize: {   //添加
                  displayStyles: {   //添加
                    backgroundColor: 'black',
                    border: 'none',
                    color: 'white'
                  },
                  modules: ['Resize', 'DisplaySize', 'Toolbar']   //添加
                }
(4) 配置build文件夹中的webpack.base.conf.js文件(不然会报错)
引入:var webpack = require('webpack');
然后在   module.exports中的最后加入下面的代码:
plugins: [
      new webpack.ProvidePlugin({
        'window.Quill': 'quill/dist/quill.js',
        'Quill': 'quill/dist/quill.js'
      })
    ]

5、上传视频自定义样式

(1) 新建 video.js
const BlockEmbed = Quill.import('blots/block/embed');
class VideoBlot extends BlockEmbed {
  static create (value) {
    let node = super.create();
    node.setAttribute('src', value.url);
    node.setAttribute('controls', value.controls);
    node.setAttribute('width', value.width);
    node.setAttribute('height', value.height);
    node.setAttribute('webkit-playsinline', true);
    node.setAttribute('playsinline', true);
    node.setAttribute('x5-playsinline', true);
    return node;
  }
  static value (node) {
    return {
      url: node.getAttribute('src'),
      controls: node.getAttribute('controls'),
      width: node.getAttribute('width'),
      height: node.getAttribute('height')
    };
  }
}
VideoBlot.blotName = 'simpleVideo';
VideoBlot.tagName = 'video';
export default VideoBlot;
(2) 组件中引入 video.js
  import VideoBlot from './video.js';
  Quill.register(VideoBlot);
  //使用在上面的insertEle()方法中,type 为 video 已经注明,这里就不写了

好了,到这里就全部配置完成(后台返回的图片和视频均为服务端地址)

最后附上一张照片

唯一的遗憾是没有太多时间去研究上传的视频的调整(持续加油!)

转载请注明

还请多多指教啦

Logo

前往低代码交流专区

更多推荐