vue实战024:Vue-Quill-Editor自定义图片上传

目录

样式重写

事件重定义

前台文件发送

后台接受文件并处理

前台接受返回数据


vue-quill-editor是个较为轻量级富文本,但是在使用vue-quill-editor我们会发现,vue-quill-editor默认插入图片是直接将图片转为base64再放入内容中,如果图片比较大的话,富文本的内容就会很大,而且也不方便我们处理。所以这里需要来重新定义图片上传功能,当我们选择图片后将图片上传服务器,服务器返回相应的图片链接,前端将图片链接插入到富文本的指定光标上位置,在提交富文本的内容的时候图片只是以图片地址提交。

样式重写

我们重新写个简单的样式,用来上传图片是使用,默认隐藏(uploadimg=false),当我们点击上传图片图标时将其显示,所以这里我们要做的就是新增HTML和CSS并且重写toolbar中image的方法。

 

事件重定义

下面要做的就是重新定义image方法,在toolbar中的headers中 我们可以给对应的标签重新定义方法,这里我们要该的是image,当我们点击时显示我们新增的样式,也就是把uploadimg=false改成uploadimg=true,所以我们直接在headers中禁用quill内部上传图片,然后写个点击事件触发新事件。

#data
toolbar:{
    container: toolbarOptions,
    handlers: {
                'image': function () {
                    this.quill.format('image', false); //禁用quill内部上传图片
                }
            }
        }
#computed
quill(){
    let quill=this.$refs.BGEditor.quill
    return quill
}
# mounted
img:{
    var imgup=document.querySelector('.quill-editor .ql-image')
    imgup.onclick= () =>{
            this.uploadimg=!this.uploadimg
    }
}

思路:我们需要做的是点击“上传到服务器”按钮将我们选择的文件发送到后台,后台拿到我们的文件后进行存储并返回我们前端文件路径,前端拿到文件的存储路径,再把路径赋给光标所在的img标签中这样就可以在文中中看到我们上传的图片了。

前台文件发送

首先要获取到上传的文件,这里我们用的是input标签,属性为file,所以这里我们没法用v-model来获取数据,这时我们需要用到$refs来定位获取,我们给input一个ref属性,然后通过let filename=this.$refs.imgfile.files[0]获取到文件对象。

注意事项:我们从前端发送文件给后端时是个文件,所以我们需要创建一个FormData对象来处理文件。

# HTML
<div class="uploadImg" v-show="uploadimg" >
    <p>图像属性</p>
    <input type="file"  ref="imgfile">
    <span>支持.jpg .gif .png .bmp.jpeg,大小不超过5M</span></br>
    <button @click="upload">上传到服务器</button>
</div>    

# models
upload(){
    let filename=this.$refs.imgfile.files[0]
    var formData = new FormData()
    formData.append("img",filename)
    this.$axios.post('http://127.0.0.1:8000/upload/',formData)
    .then(response =>{
        console.log(response.data)
    })
},

后台接受文件并处理

model创建

我们需要创建一个文件的模型,这里用来存储文件的路径,并指定文件存储位置,我定义了一个简单的模型,只有文件名和文件路径,通过参数upload_to指定上传文件的保存目录,具体的操作可以参考:Django实战009:文件上传实现过程详解

class File(models.Model):
    name = models.CharField(max_length=100)
    file = models.ImageField(upload_to='image', null=True)

    def __str__(self):
        return self.name

    class Meta:
        db_table = 'file'

路由创建

我们需要给前台一个指定的路由来找到视图,我将upload指向了views.uploadfile,也就是uploadfile方法。

from django.conf.urls import url
from user import views

urlpatterns = [
    # url(r'^login/$',views.login),
    # url(r'^register/$',views.register),
    url(r'^upload/$',views.uploadfile),
]

视图创建

现在我们需要一个视图(uploadfile)来接受前台发送的数据,通过 request.FILES.get('img')来获取文件对象,拿到文件名然后去数据库中查找该对象是否存在,如果存在我们直接返回该对象的路径,如果没有我们就新增并返回文件路径,这里我返回了一个code表示处理成功,返回一个url则是图片的文件路径。

def uploadfile(request):
    if request.method == "POST":
        fileName = request.FILES.get('img')
        imgname=fileName.name
        if not fileName:
            return HttpResponse('400')
        imgobj=models.File.objects.filter(name=imgname)
        if not imgobj:
            models.File.objects.update_or_create(name=imgname,file=fileName)
            imgurl = imgobj.first().file.url
        else:
            imgurl=imgobj.first().file.url
        info = {'code': '200', 'url': imgurl}
        return JsonResponse(info)

注意事项:这里我们用的是filter而不是get,get是获取唯一值,当没有时就会报错,如果要用就用突然try包裹起来使用,用filter则是使用了查询集,没有则返回空。

前台接受返回数据

首先我们先接受后台返回到的数据,通过code来判断数据是否处理成,如果失败则弹出“图片插入失败”提示,如果成功我们就将图片插入到光标所在位置即可。

upload(){
    let filename=this.$refs.imgfile.files[0]
    var formData = new FormData()
    formData.append("img",filename)
    console.log(FormData)
    this.$axios.post('http://127.0.0.1:8000/upload/',formData)
    .then(response =>{
        console.log(response.data)
        let quill=this.$refs.BGEditor.quill
        if(response.data['code']==200){
                //获取图片路径
                let imgurl='http://127.0.0.1:8000'+response.data['url']
                // 获取光标所在位置
                let position = quill.getSelection().index
                quill.insertEmbed(position, 'image', imgurl)
                quill.setSelection(position + 1)
                this.uploadimg=false
        }else {
            // 提示信息,需引入Message
            Message.error('图片插入失败')
        }
    }
    )
},

 

欢迎关注本人的公众号:编程手札,文章也会在公众号更新

<think>好的,用户的问题是关于在vue-quill-editor中实现自定义图片上传功能。我需要先回顾一下vue-quill-editor的基本用法,以及Quill编辑器的扩展机制。首先,vue-quill-editorVue的一个封装,用于集成Quill富文本编辑器。Quill本身支持通过模块扩展功能,比如图片上传通常需要覆盖默认的处理方式。 用户提到想要自定义图片上传,这意味着需要替换Quill默认的图片上传行为,通常是弹出一个对话框让用户选择本地图片,然后上传到服务器,再将图片URL插入到编辑器中。根据之前的经验,可能需要用到Quill的imageHandler配置,或者通过自定义模块来实现。 接下来,我需要考虑如何集成到Vue组件中。可能需要覆盖Quill的工具栏配置,添加自定义图片按钮,并绑定事件处理函数。同时,需要使用axios或其他HTTP库来处理文件上传到服务器的逻辑。此外,上传过程中可能需要显示进度条或提示信息,所以需要处理上传状态。 还要注意,Quill在插入图片时默认使用Base64编码,这会导致内容过大,所以需要替换为服务器返回的URL。因此,步骤大致包括:配置Quill图片处理函数,创建上传组件或对话框,处理文件选择,上传到服务器,获取URL并插入编辑器。 需要检查是否有相关的代码示例或文档支持这些步骤。比如,官方文档中提到的使用modules配置,或者参考社区中的解决方案,如使用vue-quill-editor的handlers选项来覆盖image处理函数。同时,可能需要使用Vue的事件机制来触发文件选择对话框,因为直接使用Quill的工具栏按钮可能需要DOM操作。 另外,用户可能在上传过程中需要处理错误,比如文件类型不支持、大小限制等,所以代码中应该包含这些验证逻辑。同时,考虑到用户体验,上传时的反馈也很重要,比如禁用按钮或显示加载状态。 最后,需要确保代码示例的正确性,比如使用正确的Vue生命周期钩子(如mounted)来初始化Quill实例,并在beforeDestroy时清理资源,避免内存泄漏。同时,样式方面可能需要调整,确保上传对话框或按钮与现有UI一致。</think>在`vue-quill-editor`中实现自定义图片上传功能,需通过以下步骤操作: --- ### 一、覆盖默认图片处理 1. **初始化Quill时配置图片处理函数** ```javascript export default { mounted() { this.quill = this.$refs.quillEditor.quill // 覆盖默认图片处理器 this.quill.getModule('toolbar').addHandler('image', this.customImageHandler) } } ``` --- ### 二、创建自定义上传逻辑 2. **实现图片选择与上传** ```javascript methods: { customImageHandler() { const input = document.createElement('input') input.setAttribute('type', 'file') input.setAttribute('accept', 'image/*') input.onchange = async () => { const file = input.files[0] // 文件类型校验 if (!/^image\/(jpe?g|png|gif)$/.test(file.type)) { return this.$message.error('仅支持JPG/PNG/GIF格式') } // 上传至服务器 const formData = new FormData() formData.append('image', file) try { const res = await axios.post('/api/upload', formData, { headers: {'Content-Type': 'multipart/form-data'}, onUploadProgress: e => { if (e.lengthComputable) { const progress = (e.loaded / e.total * 100) | 0 console.log(`上传进度: ${progress}%`) } } }) // 插入图片URL const range = this.quill.getSelection() this.quill.insertEmbed(range.index, 'image', res.data.url) } catch (err) { console.error('上传失败:', err) } } input.click() } } ``` --- ### 三、配置编辑器模块 3. **自定义工具栏配置** ```javascript editorOption: { modules: { toolbar: { container: [ ['bold', 'italic'], [{ 'header': 1 }, { 'header': 2 }], ['image'] // 保留图片按钮 ], handlers: { 'image': () => {} // 实际处理由customImageHandler完成 } } } } ``` --- ### 四、扩展功能建议 - **图片裁剪**:集成`vue-cropper`组件[^1] ```javascript import VueCropper from 'vue-cropper' export default { components: { VueCropper }, methods: { async uploadWithCrop(file) { // 调用裁剪组件预处理 } } } ``` - **进度反馈**:使用`element-ui`的进度条组件 - **错误处理**:添加网络异常和服务器错误提示 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ProgramNotes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值