Vue 中使用富文本编辑器 vue-quill-editor 与自定义上传图片及显示HTML源码

# 前言

富文本编辑器有很多,比如 UEditorSimditorwangEditorCKEditorTinyMCEFroalaQuill 等各种各样的。
我们今天主要介绍下 vue-quill-editor 以及如何自定义上传图片。

安装

npm install vue-quill-editor -S
npm install quill -S

引入

main.js 全局引入

import Vue from 'vue'
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)

=============================================

单个页面引入

import { quillEditor } from "vue-quill-editor"; //调用编辑器
import 'quill/dist/quill.core.css';
import 'quill/dist/quill.snow.css';
import 'quill/dist/quill.bubble.css';

export default{
    components: { quillEditor },
}

配置

配置功能按钮

html 
<quill-editor v-model="content" ref="myQuillEditor" :options="editorOption" style="height: 200px" />

js
editorOption: {
    placeholder: "请在这里输入",
    modules: {
        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': ['small', false, 'large', 'huge'] }], // 字体大小
                [{ 'header': [1, 2, 3, 4, 5, 6, false] }],     //几级标题
                [{ 'color': [] }, { 'background': [] }],     // 字体颜色,字体背景颜色
                [{ 'font': [] }],     //字体
                [{ 'align': [] }],    //对齐方式
                ['clean'],    //清除字体样式
                ['image']    //上传图片、上传视频  'video'
            ]
        }
    }
}

可根据项目需要自行删减

效果图如下


image.png

新增显示Html源码功能

  1. 创建 quill.eeSourceBtn.js 内容如下
class eeSourceBtn {
    constructor(quill, options) {
        let theClass = this;
        theClass.addDom(quill);
        quill.on('text-change', (delta, oldDelta, source) => {
            theClass.replaceSourceEditorContent(quill)
        })

        //create btn
        let button = document.createElement("button");
        //display button text
        button.innerHTML = "html";
        button.onclick = function() {
            theClass.showSourceEditor(quill);
        };

        //create btn container
        let buttonContainer = document.createElement("span");
        buttonContainer.setAttribute("class", "ql-formats ee-flag-source");
        buttonContainer.appendChild(button);
        //add to toolbar
        quill.container.previousSibling.appendChild(buttonContainer);
    }
    //add dom for source editor
    addDom(quill) {
        if (!quill.container.querySelector(".ql-ee-source")) {
            var txtArea = document.createElement('textarea');
            txtArea.style.cssText = "width: 100%;margin: 0px;background: rgb(249, 249, 249);box-sizing: none;font-size: 13px;outline: none;padding: 12px 15px;line-height: 1.42;font-family: Consolas, Menlo, Monaco, &quot;Courier New&quot;, monospace;position: absolute;top: 0;bottom: 0;border: none;"

            var htmlEditor = quill.addContainer('ql-ee-source')
            htmlEditor.style.cssText = "display:none";
            htmlEditor.appendChild(txtArea)
        }
    }

    //for quill editor switch
    replaceSourceEditorContent(quill) {
        let quillEditor = quill.container.querySelector(".ql-editor");
        let sourceContainer = quill.container.querySelector(".ql-ee-source");
        let sourceEditor = sourceContainer.querySelector('textarea');
        sourceEditor.value = quillEditor.innerHTML;
    }

    //add html DOM, show/hide, save event
    showSourceEditor(quill) {
        //1. find quill editor
        let quillEditor = quill.container.querySelector(".ql-editor");
        let sourceContainer = quill.container.querySelector(".ql-ee-source");
        let sourceEditor = sourceContainer.querySelector('textarea');
        //show/hide editor, value transfer
        if (sourceContainer.style.display === 'none') {
            //show source editor
            sourceContainer.style.display = '';
            sourceEditor.value = quillEditor.innerHTML;
        } else {
            //hidden source ditor
            sourceContainer.style.display = 'none';
            //set source content to quill editor
            quillEditor.innerHTML = sourceEditor.value;
        }
    }
}

window.eeSourceBtn = eeSourceBtn;
export default eeSourceBtn;
export { eeSourceBtn };
  1. 页面引入
import { Quill } from "vue-quill-editor"; 
import { eeSourceBtn } from '../quill.eeSourceBtn.js';
// 注册我们写的事件
Quill.register( 'modules/eeSourceBtn', eeSourceBtn );
  1. 在配置项里加入我们的新增的事件
editorOption: {
    placeholder: "请在这里输入",
    modules: {
        eeSourceBtn: eeSourceBtn,  // 引入我我们新增的事件
        toolbar: {
              container: [...这里是我们之前配置的功能按钮项]
        } 
    }
}

效果图如下

1640763608(1).png

多了显示Html源码的标识

自定义上传图片

问:为什么要自定义上传图片呢?
答:默认是base64格式图片,可自定义上传至文件服务器OSS等。

这里依赖element-ui的上传插件,所以我们得配置一下

安装
npm install element-ui -S

main.js 引入
import Element from "element-ui";
import "element-ui/lib/theme-chalk/index.css";
Vue.use(Element);

开始写自定义上传图片

// html
<quill-editor v-model="content" ref="myQuillEditor" :options="editorOption"  style="height: 200px" />
<!-- 用于配合编辑器自定义上传图片 -->
<el-upload class="QuillEditor-uploader" action :before-upload="QuillEditorUpload" v-show="0" />

// js
editorOption: {
    placeholder: "请在这里输入",
    modules: {
        eeSourceBtn: eeSourceBtn,
        toolbar: {
            container: [...这里是我们之前配置的功能按钮项],
            // 自定义上传图片
            handlers: {
                'image': function ( value ) {
                    if ( value ) {
                        // 触发上传插件
                        document.querySelector('.QuillEditor-uploader .el-upload__input').click()
                    } else {
                        this.quill.format( 'image', false );
                    }
                }
            }
        }
    }
}

// 调用接口上传
QuillEditorUpload(){
    let fd = new FormData();
    fd.append( 'file', f ) 
    upload( fd ).then( res => {
    if ( res.isSuccess ){
        // 获取富文本组件实例
        let quill = this.$refs.myQuillEditor.quill
        // 获取光标所在位置
        let length = quill.getSelection().index;
        // 插入图片,res.resultMsg 为服务器返回的图片链接地址
        quill.insertEmbed(length, 'image', res.resultMsg)
        // 调整光标到最后
        quill.setSelection(length + 1)
     }
    } )
}

其他方法

编辑器还提供了其他方法供大家使用:

@blur="onEditorBlur($event)" 
@focus="onEditorFocus($event)" 
@change="onEditorChange($event)" 
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容