vue vue-quill-editor 富文本编辑器 (图片问题)+拦截粘贴动作 将粘贴的图片上传服务器 + 一个页面渲染多个富文本编辑器(使用场景循环遍历 个数不定)

1.不管粘贴图片的问题

富文本编辑器默认的方式是图片转成base64 但是这个一张图片可能就把后台的默认字符长度占满了 所以需要先服务端上传图片的方式 代码如下

封装组件的方式应该复制了是能直接使用的

<template>
    <div class="vue-quill-editor-com">
        <quill-editor v-model="content" ref="myQuillEditor" :options="editorOption" @blur="onEditorBlur($event)"
            @focus="onEditorFocus($event)" @change="onEditorChange($event)">
        </quill-editor>
        <input type="file" accept=".png,.jpg,.jpeg" @change="changePic" multiple id="quillPicUpload"
            style="display: none" />
        <input type="file" accept="video/*" @change="changeVideo" id="quillVideoUpload" style="display: none" />
        <input type="file" @change="changeFile" id="quillFileUpload" style="display: none" />
    </div>
</template>
  
<script>
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'

import { quillEditor } from 'vue-quill-editor'
import http from "@/api/http";
import { updateimg } from "@/api/SpliceUrl/SpliceUrl";
export default {
    components: {
        quillEditor
    },
    data() {
        return {
            content: `<p>hello world</p>`,
            editorOption: {
                //  富文本编辑器配置
                modules: {
                    //工具栏定义的
                    toolbar: {
                        container: [
                            ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线 -----['bold', 'italic', 'underline', 'strike']
                            ['blockquote', 'code-block'], // 引用  代码块-----['blockquote', 'code-block']
                            [{ header: 1 }, { header: 2 }], // 1、2 级标题-----[{ header: 1 }, { header: 2 }]
                            [{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表-----[{ list: 'ordered' }, { list: 'bullet' }]
                            [{ script: 'sub' }, { script: 'super' }], // 上标/下标-----[{ script: 'sub' }, { script: 'super' }]
                            [{ indent: '-1' }, { indent: '+1' }], // 缩进-----[{ indent: '-1' }, { indent: '+1' }]
                            [{ direction: 'rtl' }], // 文本方向-----[{'direction': 'rtl'}]
                            [{ size: ['12px', '100%', '16px', '18px', '20px', '22px', '24px', '28px', '32px', '48px'] }], // 字体大小-----[{ size: ['small', false, 'large', 'huge'] }]
                            [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题-----[{ header: [1, 2, 3, 4, 5, 6, false] }]
                            [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色-----[{ color: [] }, { background: [] }]
                            [{ font: [] }], // 字体种类-----[{ font: [] }]
                            [{ align: [] }], // 对齐方式-----[{ align: [] }]
                            ['clean'], // 清除文本格式-----['clean']
                            ['image'] // 链接、图片、视频-----['link', 'image', 'video']
                        ],
                        handlers: {
                            image: function (value) {
                                if (value) {
                                    document.querySelector('#quillPicUpload').click() // 劫持原来的图片点击按钮事件
                                } else {
                                    this.quill.format('image', false)
                                }
                            },
                            video: function (value) {
                                if (value) {
                                    document.querySelector('#quillVideoUpload').click()
                                } else {
                                    // return
                                    this.quill.format('video', false)
                                }
                            },
                            // 文件上传
                            upload: value => {
                                if (value) {
                                    document.querySelector('#quillFileUpload').click()
                                } else {
                                    this.quill.format('upload', false)
                                }
                            }
                        }
                    }
                },
                //主题
                theme: 'snow',
                placeholder: '请输入正文'
            }
        }
    },
    created() {
        this.content = this.editorContent
    },
    props: {
        editorContent: {
            type: String,
            default: ''
        }
    },
    methods: {
        //失去焦点事件
        onEditorBlur(quill) {
            // console.log('editor blur!', quill)
        },
        //获得焦点事件
        onEditorFocus(quill) {
            // console.log('editor focus!', quill)
        },
        // 准备富文本编辑器
        onEditorReady(quill) {
            // console.log('editor ready!', quill)
        },
        //内容改变事件
        onEditorChange({ quill, html, text }) {
            // console.log('editor change!', quill, html, text)
            this.content = html
            this.$emit('change', { quill, html, text })
        },
        // 图片上传
        changePic(e) {
            let fileList = e.target.files
            let formData = new FormData()
            for (let i = 0; i < fileList.length; i++) {
                formData.append('update_image', fileList[i])
            }
            http
                .post(updateimg, formData)
                .then(res => {
                    //console.log(res.data.update_image)
                    if (res.data.update_image) {
                        let picList = res.data.update_image
                        let quill = this.$refs.myQuillEditor.quill

                        let index = quill.getSelection().index // 光标位置
                        quill.insertEmbed(index, 'image', picList) // 插入图片  图片地址
                        // 调整光标到最后
                        quill.setSelection(index + 1) // 光标后移一位

                    } else {
                        this.$message({
                            message: '图片上传失败:',
                            type: 'error'
                        })
                    }
                })
                .catch(err => {
                    console.log(err)
                })
        },
        // 上传视频
        changeVideo(e) {
            this.$message.warning('不支持上传视频')
        },
        // 上传文件
        changeFile(e) { }
    }
}
</script>
  
<style lang='scss'>
.vue-quill-editor-com {
    line-height: normal !important;
    // height: 500px;
    min-height: 400px;
    height: 400px;
}

.ql-editor {
    height: 350px !important;
}

.ql-snow .ql-tooltip[data-mode='link']::before {
    content: '请输入链接地址:';
}

.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
    border-right: 0px;
    content: '保存';
    padding-right: 0px;
}

.ql-snow .ql-tooltip[data-mode='video']::before {
    content: '请输入视频地址:';
}

.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
    content: 'normal';
}

.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';
}

.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';
}

.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';
}

.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';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='22px']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='22px']::before {
    content: '22px';
}

.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';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='28px']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='28px']::before {
    content: '28px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='32px']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='32px']::before {
    content: '32px';
}

.ql-snow .ql-picker.ql-size .ql-picker-label[data-value='48px']::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value='48px']::before {
    content: '48px';
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.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::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
    content: '标准字体';
}

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='serif']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='serif']::before {
    content: '衬线字体';
}

.ql-snow .ql-picker.ql-font .ql-picker-label[data-value='monospace']::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value='monospace']::before {
    content: '等宽字体';
}
</style>

2.管粘贴的问题

拦截粘贴的图片并转换成文件上传到服务端

//配置项增加
  //图片粘贴拦截
                    clipboard: {
                        // 粘贴板,处理粘贴图片  *** 主要是这里
                        matchers: [[Node.ELEMENT_NODE, this.stopimgclip]],
                    },
//方法
 stopimgclip(node, Delta) {
            let ops = []
            Delta.ops.forEach(op => {
                if (op.insert && typeof op.insert === 'string') {
                    ops.push({
                        insert: op.insert,
                    })
                } else { //给出提醒
                    if (op.insert.image) {
                        //给个提示
                        this.$message({
                            message: '粘贴的内容是图片',
                            type: 'warning',

                        })
                        //调用方法
                        this.mybase64tofileandupload(op.insert.image)
                        // return
                    }
                }
            })
            Delta.ops = ops
            return Delta
        },
 stopimgclip(node, Delta) {
            let ops = []
            Delta.ops.forEach(op => {
                if (op.insert && typeof op.insert === 'string') {
                    ops.push({
                        insert: op.insert,
                    })
                } else { //给出提醒
                    if (op.insert.image) {
                        //给个提示
                        this.$message({
                            message: '粘贴的内容是图片',
                            type: 'warning',

                        })
                        //调用方法
                        this.mybase64tofileandupload(op.insert.image)
                        // return
                    }
                }
            })
            Delta.ops = ops
            return Delta
        },

3. 一个页面渲染多个富文本编辑器(使用场景循环遍历 个数不定)

虽然可离谱但是业务的使用场景就是这个昨天百度了一些经验都是些的定死的没有符合我这种需求的 所以回去之后夜不能寐 在梦里一顿瞎想 有了个浅显的方案 还真别说今天来了之后一试验 还真的能用 感恩睡梦中的自己

 我们在页面上使用不正常的原因无外乎就是有些用的是dom操作要拿确定的Id 和ref之类的去查 那我们到这里其实可以把他们变的不一样 把组件的ref 和标签的通过Props传进来的这种方式 就可以做到区分开了 大家各司其职 谁也不会发癫不正常了代码如下
 

//第一步改html 部分
 <quill-editor v-model="content" :ref="quillref" :options="editorOption" @blur="onEditorBlur($event)"
            @focus="onEditorFocus($event)" @change="onEditorChange($event)">
        </quill-editor>
        <input type="file" accept=".png,.jpg,.jpeg" @change="changePic" multiple :id="picupid" style="display: none" />

//第二步 props
 quillref: {
            type: String,
            default: 'myQuillEditor'
        },
        picupid: {
            type: String,
            default: 'quillPicUpload'
        },

//第三步 拦截方法那里改一下 不然拿不到当前环境的东西
 image: (value)=> {
                                if (value) {
                                    document.querySelector('#'+this.picupid).click() // 劫持原来的图片点击按钮事件
                                } else {
                                    //this.quill
                                    this.$refs[`${this.quillref}`].quill.format('image', false)
                                }
                            },
// 然后下面那种填东西的改一下
let quill = _that.$refs[`${_that.quillref}`].quill

// 使用的时候
 <div v-for="item in 4" :key="item">
                    {{ item }}
                    <vueQuillEditor :picupid="'quillPicUpload'+item" :quillref="'myQuillEditor'+item" v-if="myquillshow" :editorContent="'1111'" @change="editorChange"></vueQuillEditor>
                </div>

  • 9
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值