Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

简单:直接重写图片上传事件实现图片上传到服务器 #134

Open
NextBoy opened this issue Dec 28, 2017 · 11 comments
Open

简单:直接重写图片上传事件实现图片上传到服务器 #134

NextBoy opened this issue Dec 28, 2017 · 11 comments

Comments

@NextBoy
Copy link

NextBoy commented Dec 28, 2017

需求概述

vue-quill-editor是我们再使用vue框架的时候常用的一个富文本编辑器,在进行富文本编辑的时候,我们往往要插入一些图片,vue-quill-editor默认的处理方式是直接将图片转成base64编码,这样的结果是整个富文本的html片段十分冗余,通常来讲,每个服务器端接收的post的数据大小都是有限制的,这样的话有可能导致提交失败,或者是用户体验很差,数据要传递很久才全部传送到服务器。
因此,在富文本编辑的过程中,对于图片的处理,我们更合理的做法是将图片上传到服务器,再将图片链接插入到富文本中,以达到最优的体验。
废话不多说,接下来直接看如何改造

改造分析

查阅网上的资料,我感觉提供的方案都不是特别友好,网上搜索的基本都是这一个方法
配合 element-ui 实现上传图片/视频到七牛或者是直接重新写一个按钮来进行自定义图片操作

坦白讲,上面这2个方法都很特别,也的确有效果,但是我个人还是觉得不完美,第一个方法写得太麻烦,第二个方法有点投机取巧。
结合上面两种方法以及官方的文档,我这里提供一个新的改造思路给大家参考。

引入element-ui

和第一种方法类似,为了更好的控制上传的图片,我这里也是引用了element-ui的上传图片组件

<template>
    <div>
        <!-- 图片上传组件辅助-->
        <el-upload
                class="avatar-uploader"
                :action="serverUrl"
                name="img"
                :headers="header"
                :show-file-list="false"
                :on-success="uploadSuccess"
                :on-error="uploadError"
                :before-upload="beforeUpload">
        </el-upload>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                serverUrl: '',  // 这里写你要上传的图片服务器地址
                header: {token: sessionStorage.token}  // 有的图片服务器要求请求头需要有token  
            }
        },
        methods: {
            // 上传图片前
            beforeUpload(res, file) {},
            // 上传图片成功
            uploadSuccess(res, file) {},
            // 上传图片失败
            uploadError(res, file) {}
        }
    }
</script>

这里要使用element-ui主要有2个好处

  • 可以对图片上传前,图片上传成功,图片上传失败等情况进行操作,也就是代码中的
  :on-success="uploadSuccess"  //  图片上传成功
  :on-error="uploadError"  // 图片上传失败
  :before-upload="beforeUpload"  // 图片上传前

引入vue-quill-editor

这里对于如何安装和引入vue-quill-editor和就不多做陈述了,不清楚的同学自己Google下哈。
在代码中写入vue-quill-editor后如下

<template>
    <div>
        <!-- 图片上传组件辅助-->
        <el-upload
                class="avatar-uploader"
                :action="serverUrl"
                name="img"
                :headers="header"
                :show-file-list="false"
                :on-success="uploadSuccess"
                :on-error="uploadError"
                :before-upload="beforeUpload">
        </el-upload>
        <!--富文本编辑器组件-->
       <el-row v-loading="uillUpdateImg">
        <quill-editor
                v-model="detailContent"
                ref="myQuillEditor"
                :options="editorOption"
                @change="onEditorChange($event)"
                @ready="onEditorReady($event)"
        >
        </quill-editor>
       </el-row>
    </div>
</template>
<script>
    export default {
        data() {
            return {
                quillUpdateImg: false, // 根据图片上传状态来确定是否显示loading动画,刚开始是false,不显示
                serverUrl: '',  // 这里写你要上传的图片服务器地址
                header: {token: sessionStorage.token},  // 有的图片服务器要求请求头需要有token之类的参数,写在这里
                detailContent: '', // 富文本内容
                editorOption: {}  // 富文本编辑器配置
            }
        },
        methods: {
            // 上传图片前
            beforeUpload(res, file) {},
            // 上传图片成功
            uploadSuccess(res, file) {},
            // 上传图片失败
            uploadError(res, file) {}
        }
    }
</script>

这里可以看到我们用一个包裹我们的富文本组件,是为了使用loading动画,就是v-loading这个设置

重写点击图片按钮事件

从下图可以看到,默认的配置中,整个工具栏具备了所有的功能,自然也包括红圈中的图片上传功能了。
那么接下来我们要怎么去重写这个按钮的事件呢。
clipboard.png

很简单,我们需要在editorOption配置中这么写

export default {
data() {
            return {
                serverUrl: '',  // 这里写你要上传的图片服务器地址
                header: {token: sessionStorage.token},  // 有的图片服务器要求请求头需要有token之类的参数,写在这里
                detailContent: '', // 富文本内容
                editorOption: {
                    placeholder: '',
                    theme: 'snow',  // or 'bubble'
                    modules: {
                        toolbar: {
                            container: toolbarOptions,  // 工具栏
                            handlers: {
                                'image': function (value) {
                                    if (value) {
                                        document.querySelector('#quill-upload input').click()
                                    } else {
                                        this.quill.format('image', false);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
}

配置中的handlers是用来定义自定义程序的,然而我们配置完后会懵逼地发现,整个富文本编辑器的工具栏的图片上传等按钮都不见了 只保留了几个基本的富文本功能。

这个是因为添加自定义处理程序将覆盖默认的工具栏和主题行为
因此我们要再自行配置下我们需要的工具栏,所有功能的配置如下,大家可以按需配置

<script>
// 工具栏配置
const toolbarOptions = [
  ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
  ['blockquote', 'code-block'],

  [{'header': 1}, {'header': 2}],               // custom button values
  [{'list': 'ordered'}, {'list': 'bullet'}],
  [{'script': 'sub'}, {'script': 'super'}],      // superscript/subscript
  [{'indent': '-1'}, {'indent': '+1'}],          // outdent/indent
  [{'direction': 'rtl'}],                         // text direction

  [{'size': ['small', false, 'large', 'huge']}],  // custom dropdown
  [{'header': [1, 2, 3, 4, 5, 6, false]}],

  [{'color': []}, {'background': []}],          // dropdown with defaults from theme
  [{'font': []}],
  [{'align': []}],
  ['link', 'image', 'video'],
  ['clean']                                         // remove formatting button
]

export default {
data() {
 return {
editorOption: {
          placeholder: '',
          theme: 'snow',  // or 'bubble'
          modules: {
            toolbar: {
              container: toolbarOptions,  // 工具栏
              handlers: {
                'image': function (value) {
                  if (value) {
                    alert(1)
                  } else {
                    this.quill.format('image', false);
                  }
                }
              }
            }
          }
        }
    }
 }
}

</script>

由于这里的工具栏配置列举了所有,看起来很长一堆,我建议大家可以写在单独一个文件,然后再引入,美观一点

自定义按钮事件打开上传图片

经过上面的配置,大家点击一下图片,可以看出弹出了个1,说明我们的自定义事件生效了,那么接下来,大家的思路是不是就很清晰啦?
我们需要在handles里面继续完善我们的图片点击事件。

  • 第一步,点击按钮选择本地图片
handlers: {
           'image': function (value) {
             if (value) {
             // 触发input框选择图片文件
                document.querySelector('.avatar-uploader input').click()
               } else {
                this.quill.format('image', false);
              }
           }
        }

在这里我们的自定义事件就结束了,接下来图片上传成功或者失败都由

 :on-success="uploadSuccess"  //  图片上传成功
  :on-error="uploadError"  // 图片上传失败
  :before-upload="beforeUpload"  // 图片上传前

这三个函数来处理

 // 富文本图片上传前
            beforeUpload() {
                // 显示loading动画
                this.quillUpdateImg = true
            },
            
            uploadSuccess(res, file) {
                // res为图片服务器返回的数据
                // 获取富文本组件实例
                let quill = this.$refs.myQuillEditor.quill
                // 如果上传成功
                if (res.code === '200' && res.info !== null) {
                    // 获取光标所在位置
                    let length = quill.getSelection().index;
                    // 插入图片  res.info为服务器返回的图片地址
                    quill.insertEmbed(length, 'image', res.info)
                    // 调整光标到最后
                    quill.setSelection(length + 1)
                } else {
                    this.$message.error('图片插入失败')
                }
                // loading动画消失
                this.quillUpdateImg = false
            },
       
            // 富文本图片上传失败
            uploadError() {
                // loading动画消失
                this.quillUpdateImg = false
                this.$message.error('图片插入失败')
            }

好了,本文就讲到这,目前运行良好,整个文章的代码比较多,但是实际上需要去深入理解的地方很少,我们只是简单重定义了图片按钮的触发事件。
对了,大家别忘记安装element-ui和vue-quill-editor哦。
如果有错误,欢迎大家多提提意见,希望这篇文章能帮到有需要的人。

@merrylmr
Copy link

请问:同一个单页面中有多个富文本编辑器,如何解决自定义图片上传的功能?按照上面的方法行不通,只有第一个编辑器能够上传图片,第二个编辑器就不行了,求开发思路??? @NextBoy

@NextBoy
Copy link
Author

NextBoy commented Jan 11, 2018

我QQ 920026184 ,加我说下情况哈 @merrylmr

@merrylmr
Copy link

好的 我加了你了,同意一哈哦哦。 @NextBoy

@liuyongwei0
Copy link

我按照你的这种方法试了下,也是可以插入图片的,但是,我的一个页面有三个富文本剪辑器,不管点击第几个上传图片,他都插入到了最后那个quill富文本,我刚才也加你Q了,希望同意下 @NextBoy

@iblues
Copy link

iblues commented Jan 26, 2018

多个富文本出错是因为
document.querySelector('.avatar-uploader input').click()这句话 都触发的同一个上传组建.
这个自己改下

@EleShader
Copy link

我按照你的方法,let length = quill.getSelection().index;这一步就报错,然后我try{}catch一下后,在后面 quill.insertEmbed(length, "image", res.data.filepath);同样在编辑器中没有渲染出来服务器给的图片地址,求大神给出答案呀!!

@EleShader
Copy link

image

@EleShader
Copy link

大神给个解释呀!!!

@OldDream
Copy link

老铁牛逼!好用!!!!

@yuzhanglong
Copy link

谢谢前辈~~

@sdrpsps
Copy link

sdrpsps commented Sep 29, 2022

好用!谢谢!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants