Vue-Quill-Editor在vue中的使用方式

☞☞ 个人主页欢迎访问 ☜☜

官网:Vue-Quill-Editor
官网中的几个案例的代码戳这里查看

1. 安装vue-quill-editor

npm install vue-quill-editor -S

2. 安装quill

npm install quill -S

3. 引入

import { quillEditor } from 'vue-quill-editor' // 调用富文本编辑器
import 'quill/dist/quill.snow.css' // 富文本编辑器外部引用样式  三种样式三选一引入即可
//import 'quill/dist/quill.core.css'
//import 'quill/dist/quill.bubble.css'
import * as Quill from 'quill'; // 富文本基于quill

4. To use

<!-- template部分 -->
<quill-editor
    v-model="content"
    ref="myQuillEditor"
    :options="editorOption"
    @focus="onEditorFocus($event)"
    @blur="onEditorBlur($event)"
    @change="onEditorChange($event)">
</quill-editor>

<!-- js data部分 -->
editor: null,   // 富文本编辑器对象
content: `<p></p><p><br></p><ol></ol>`, // 富文本编辑器默认内容
editorOption: { //  富文本编辑器配置
    modules: {
        toolbar: '#toolbar'
    },
    theme: 'snow',
    placeholder: '请输入正文'
},

<!-- js mounted部分 -->
this.editor = this.$refs.myQuillEditor.quill;

<!-- js beforeDestroy部分 -->
this.editor = null;
delete this.editor;

<!-- js methods部分 -->
// 准备富文本编辑器
onEditorReady (editor) {},
// 富文本编辑器 失去焦点事件
onEditorBlur (editor) {},
// 富文本编辑器 获得焦点事件
onEditorFocus (editor) {},
// 富文本编辑器 内容改变事件
onEditorChange (editor) {},

<!-- js components部分 -->
components: {
    quillEditor
}

5. 如果想自定义工具栏:

<!-- template部分 -->
<div id="toolbar" slot="toolbar">
    <button class="ql-bold" title="加粗">Bold</button>
    <select class="ql-header" title="段落格式">
        <option selected>正文</option>
        <option value="2">标题1</option>
        <option value="3">标题2</option>
        <option value="4">标题3</option>
    </select>
    <button class="ql-list" value="ordered" title="有序列表"></button>
    <button class="ql-list" value="bullet" title="无序列表"></button>
    <select class="ql-color" value="color" title="字体颜色"></select>
    <span class="icon-pic custom-icon" title="图片" @click="insertImgClick($event)"></span>  <!-- 插入图片 -->
    <span class="icon-video custom-icon" title="视频" @click="insertImgClick($event)"></span>  <!-- 插入视频 -->
</div>
<input style="display: none;" type="file" id="insert_image" @change="fileInsert($event)">  <!-- 选择图片input -->
<input style="display: none;" type="file" id="insert_video" @change="fileInsert($event)">  <!-- 选择视频input -->

<!-- js methods部分 -->
// 富文本编辑器 点击插入图片或者视频
insertImgClick (e) {
    if (e.target.className.indexOf('icon-pic') != -1) {
        document.getElementById('insert_image').click();
    } else if (e.target.className.indexOf('icon-video') != -1) {
        document.getElementById('insert_video').click();
    }
},
// 富文本编辑器 点击插入图片或者视频上传并预览
fileInsert (e) {
    var oFile = e.target.files[0];
    if (typeof (oFile) === 'undefined') {
        return;
    }
    let sExtensionName = oFile.name.substring(oFile.name.lastIndexOf('.') + 1).toLowerCase();   // 文件扩展名
    let sfileType = ''; // 上传文件类型
    if (e.target.id == 'insert_image') {
        sfileType = 'image'
        if (sExtensionName !== 'png' && sExtensionName !== 'jpg' && sExtensionName !== 'jpeg') {
            alert('不支持该类型图片');
            return;
        }
    }
    if (e.target.id == 'insert_video') {
        sfileType = 'video';
        if (sExtensionName !== 'mp4' && sExtensionName !== 'avi' && sExtensionName !== 'mov') {
            alert('不支持该类型视频');
            return;
        }
        let maxSize = 100*1024*1024;    // 100MB
        if (oFile.size > maxSize) {
            alert('上传视频大小不能超过100MB');
            return;
        }
    }
    var reader = new FileReader();
    reader.readAsDataURL(oFile);
    reader.onloadend = () => {
        let formData = new FormData(); // 通过formdata上传
        formData.append('file', oFile);
        let sUrl = '';
        if (sfileType == 'image') {
            sUrl = 'Pic';
        }
        if (sfileType == 'video') {
            sUrl = 'Vie';
        }
        var url = this.api_config + '/dealerIndex/upload' + sUrl + '.htm';
        this.axios.post(url, formData, {
            headers: { 'Content-Type': 'multipart/form-data' }
        }).then((res) => {
            this.editor.insertEmbed(this.editor.selection.savedRange.index, sfileType, res.data.data);  // 这个方法用来手动插入dom到编辑器里
            let isAndroid = this.$is_android(); // 判断是ios还是android
            if (isAndroid) {
                $('video').removeAttr('controls');
                $('video').attr('x5-video-player-type', 'h5');
            }
            this.editor.setSelection(this.editor.selection.savedRange.index + 1);  // 这个方法可以获取光标位置
        }).catch((response) => {
            console.log('失败', response);
        })
    }
},

关于编辑器里面的一些操作可以到quill官方查看,用法和配置项的的介绍很详细,很好用

6. 如果想更好地操作插入的video,可以把iframe改成h5的video,通过下面这段代码:

import { Quill } from 'vue-quill-editor'

// 源码中是import直接倒入,这里要用Quill.import引入
const BlockEmbed = Quill.import('blots/block/embed')
const Link = Quill.import('formats/link')

const ATTRIBUTES = ['height', 'width']

class Video extends BlockEmbed {
  static create (value) {
    const node = super.create(value)
    // 添加video标签所需的属性
    node.setAttribute('controls', 'controls')   // 控制播放器
    node.setAttribute('type', 'video/mp4')
    node.setAttribute('style', 'object-fit:fill;width: 100%;')
    node.setAttribute('preload', 'auto')    // auto - 当页面加载后载入整个视频  meta - 当页面加载后只载入元数据  none - 当页面加载后不载入视频
    node.setAttribute('webkit-playsinline', 'true') // 兼容ios 不全屏播放
    node.setAttribute('playsinline', 'true')
    node.setAttribute('x-webkit-airplay', 'allow')
    // node.setAttribute('x5-video-player-type', 'h5') // 启用H5播放器,是wechat安卓版特性
    node.setAttribute('x5-video-orientation', 'portraint') // 竖屏播放 声明了h5才能使用  播放器支付的方向,landscape横屏,portraint竖屏,默认值为竖屏
    node.setAttribute('x5-playsinline', 'true') // 兼容安卓 不全屏播放
    node.setAttribute('x5-video-player-fullscreen', 'true')    // 全屏设置,设置为 true 是防止横屏
    node.setAttribute('src', this.sanitize(value))
    return node
  }

  static formats (domNode) {
    return ATTRIBUTES.reduce((formats, attribute) => {
      if (domNode.hasAttribute(attribute)) {
        formats[attribute] = domNode.getAttribute(attribute)
      }
      return formats
    }, {})
  }

  static sanitize (url) {
    return Link.sanitize(url) // eslint-disable-line import/no-named-as-default-member
  }

  static value (domNode) {
    return domNode.getAttribute('src')
  }

  format (name, value) {
    if (ATTRIBUTES.indexOf(name) > -1) {
      if (value) {
        this.domNode.setAttribute(name, value)
      } else {
        this.domNode.removeAttribute(name)
      }
    } else {
      super.format(name, value)
    }
  }

  html () {
    const { video } = this.value()
    return `<a href="${video}">${video}</a>`
  }
}
Video.blotName = 'video' // 这里不用改,楼主不用iframe,直接替换掉原来,如果需要也可以保留原来的,这里用个新的blot
Video.className = 'ql-video'
Video.tagName = 'video' // 用video标签替换iframe

export default Video

然后再把它引入到有编辑器的那个文件里:

import Video from '../../plugins/video.js'; // 插入h5 video视频
Quill.register(Video, true);  // 注册video

就是这么多了,很简单的,如果有什么问题的小伙伴们可以在这里给我留言哈,对大家有帮助的内容可以提供下,一起学习共同进步

如果喜欢本文的话单击爱心加关注谢谢O(∩_∩)O~

欢迎访问我的GitHub,喜欢的可以star,项目随意fork,支持转载但要下标注

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

推荐阅读更多精彩内容

  • 基于Vue的一些资料 内容 UI组件 开发框架 实用库 服务端 辅助工具 应用实例 Demo示例 element★...
    尝了又尝阅读 1,138评论 0 1
  • 优秀的富文本编辑器有很多,比如:UEditor,wangEditor 等,但并不是每个都能在移动端有很好的表现。 ...
    solocoder阅读 12,314评论 1 8
  • ☞☞ 个人主页欢迎访问 ☜☜ 最近在开发一个移动端项目微信公众号,前端框架我用当然是Vue,期间遇到了很多问题,在...
    苏日俪格阅读 7,826评论 7 51
  • UI组件 element- 饿了么出品的Vue2的web UI工具套件 Vux- 基于Vue和WeUI的组件库 m...
    小姜先森o0O阅读 9,378评论 0 72
  • “走过路过,千万不要错过,荧光棒一元四根,好玩不贵喽,机不可失时不再来……”你一定很好奇,我在干什么呢?告诉...
    宝旺阅读 408评论 0 0