vue-quill-editor上传图片到服务器

2018-01-13 发布

vue-quill-editor-upload : 实现vue-quill-editor上传图片到服务器

install

  • npm

    npm install vue-quill-editor-upload --save

基本使用

<template>
  <!-- bidirectional data binding(双向数据绑定) -->
  <quill-editor v-model="content"
                ref="myQuillEditor"
                :options="editorOption">
  </quill-editor>
</template>

<script>
  import {quillRedefine} from 'vue-quill-editor-upload'
  import {quillEditor} from 'vue-quill-editor'
  export default {
    components: {quillEditor, quillRedefine},
    data () {
      return {
        content: '',
        editorOption: {}  // 必须初始化为对象 init  to Object
      }
    },
    created () {
      this.editorOption = quillRedefine(
        {
          // 图片上传的设置
          uploadConfig: {
            action: '',  // 必填参数 图片上传地址
            // 必选参数  res是一个函数,函数接收的response为上传成功时服务器返回的数据
            // 你必须把返回的数据中所包含的图片地址 return 回去
            res: (respnse) => {
              return respnse.info
            },
            name: 'img'  // 图片上传参数名
          }
        }
      )
      console.log(this.editorOption)
    }
  }
</script>

use

You have to install vue-quill-editor first.

请确保您已安装了 vue-quill-editor

  • import

    import {quillRedefine} from 'vue-quill-editor-upload'

quillRedefine是一个函数

quillRedefine 可接收的所有参数(all params)

{
          // 图片上传的设置
          uploadConfig: {
            action: '',  // 必填参数 图片上传地址
            // 必选参数  res是一个函数,函数接收的response为上传成功时服务器返回的数据
            // 你必须把返回的数据中所包含的图片地址 return 回去
            res: (respnse) => {
              return respnse.info
            },
            methods: 'POST',  // 可选参数 图片上传方式  默认为post
            token: sessionStorage.token,  // 可选参数 如果需要token验证,假设你的token有存放在sessionStorage
            name: 'img',  // 可选参数 文件的参数名 默认为img
            size: 500,  // 可选参数   图片限制大小,单位为Kb, 1M = 1024Kb
            accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon',  // 可选参数 可上传的图片格式
            // start: function (){}
            start: () => { },  // 可选参数 接收一个函数 开始上传数据时会触发
            end: () => { },  // 可选参数 接收一个函数 上传数据完成(成功或者失败)时会触发
            success: () => {},  // 可选参数 接收一个函数 上传数据成功时会触发
            error: () => { }  // 可选参数 接收一个函数 上传数据中断时会触发
          },
          // 以下所有设置都和vue-quill-editor本身所对应
          placeholder: '',  // 可选参数 富文本框内的提示语
          theme: '',  // 可选参数 富文本编辑器的风格
          toolOptions: [],  // 可选参数  选择工具栏的需要哪些功能  默认是全部
          handlers: {}  // 可选参数 重定义的事件,比如link等事件
}
  • demo

first

you must to do: :options="editorOption" to bound Parameters

你必须绑定option :options="editorOption"

<template>
  <!-- bidirectional data binding(双向数据绑定) -->
  <quill-editor 
                :options="editorOption">
  </quill-editor>
</template>

second

return editorOption

必须在return 中书写editorOPtion 并且设置默认为空对象

 data () {
      return {
        content: '',
        editorOption: {}  // 必须初始化为对象 init  to Object
      }
    }

three

init in created

在created生命周期中生成实际数据

created () {
      this.editorOption = quillRedefine(
        {
          // 图片上传的设置
          uploadConfig: {
            action:  '',  // 必填参数 图片上传地址
            // 必选参数  res是一个函数,函数接收的response为上传成功时服务器返回的数据
            // 你必须把返回的数据中所包含的图片地址 return 回去
            res: (respnse) => {
              return respnse.info  // 这里切记要return回你的图片地址
            }
          }
        }
      )
     // console.log(this.editorOption)
    }

注意事项 (matters need attention)

由于不同的用户的服务器返回的数据格式不尽相同

因此

在uploadConfig中,你必须如下操作

 // 你必须把返回的数据中所包含的图片地址 return 回去
 res: (respnse) => {
    return respnse.info  // 这里切记要return回你的图片地址
 }

比如你的服务器返回的成功数据为

{
code: 200,
starus: true,
result: {
    img: 'http://placehold.it/100x100' // 服务器返回的数据中的图片的地址
 }
}

那么你应该在参数中写为:

 // 你必须把返回的数据中所包含的图片地址 return 回去
 res: (respnse) => {
    return respnse.result.img  // 这里切记要return回你的图片地址
 }

example

完整用例

<template>
  <!-- bidirectional data binding(双向数据绑定) -->
  <quill-editor v-model="content"
                ref="myQuillEditor"
                :options="editorOption">
  </quill-editor>
</template>

<script>
  import {quillRedefine} from 'vue-quill-editor-upload'
  import {quillEditor} from 'vue-quill-editor'
  export default {
    components: {quillEditor, quillRedefine},
    data () {
      return {
        content: '',
        editorOption: {}  // 必须初始化为对象 init  to Object
      }
    },
    created () {
      this.editorOption = quillRedefine(
        {
          // 图片上传的设置
          uploadConfig: {
            action: '',  // 必填参数 图片上传地址
            // 必选参数  res是一个函数,函数接收的response为上传成功时服务器返回的数据
            // 你必须把返回的数据中所包含的图片地址 return 回去
            res: (respnse) => {
              return respnse.info
            },
            methods: 'POST',  // 可选参数 图片上传方式  默认为post
            token: sessionStorage.token,  // 可选参数 如果需要token验证,假设你的token有存放在sessionStorage
            name: 'img',  // 可选参数 文件的参数名 默认为img
            size: 500,  // 可选参数   图片限制大小,单位为Kb, 1M = 1024Kb
            accept: 'image/png, image/gif, image/jpeg, image/bmp, image/x-icon',  // 可选参数 可上传的图片格式
            // start: function (){}
            start: () => {
            },  // 可选参数 接收一个函数 开始上传数据时会触发
            end: () => {
            },  // 可选参数 接收一个函数 上传数据完成(成功或者失败)时会触发
            success: () => {
            },  // 可选参数 接收一个函数 上传数据成功时会触发
            error: () => {
            }  // 可选参数 接收一个函数 上传数据中断时会触发
          },
          // 以下所有设置都和vue-quill-editor本身所对应
          placeholder: '',  // 可选参数 富文本框内的提示语
          theme: '',  // 可选参数 富文本编辑器的风格
          toolOptions: [],  // 可选参数  选择工具栏的需要哪些功能  默认是全部
          handlers: {}  // 可选参数 重定义的事件,比如link等事件
        }
      )
      console.log(this.editorOption)
    }
  }
</script>

上面的代码是我从别的地方搬过来的 下面的代码是我的 可以根据我的代码结合一块看

我认为最重要的一点就是母吆盲目的复制粘贴,因为开发人员写不出来就会急躁,故要将该考虑的都考虑到然后进行操作

<template>
    <div id="articleAdd">
        <div class="search">
            <el-form  label-width="80px">
                <el-form-item label="标题">
                    <el-input clearable placeholder="请输入标题" v-model="form.title"></el-input>
                </el-form-item>

                <el-form-item label="作者">
                    <el-input clearable="clearable" placeholder="请输入作者" v-model="form.author"></el-input>
                </el-form-item>

                <el-form-item label="权重">
                    <el-input clearable="clearable" placeholder="请输入权重" v-model="form.sort"></el-input>
                </el-form-item>

                <el-form-item label="封面">
                    <el-upload class="upload-demo" :action="uploadUrl" :data="prefix" :file-list="coverBox"
                        :on-remove="handleRemove" :on-success="handleAvatarSuccess"
                        list-type="picture">
                        <el-button size="small" type="primary">点击上传</el-button>
                    </el-upload>
                </el-form-item>
                <el-form-item label="上传类型">
                    <el-radio-group v-model="upLoadType">
                        <el-radio :label="1">上传链接</el-radio>
                        <el-radio :label="2">上传文章</el-radio>
                    </el-radio-group>
                </el-form-item>

            </el-form>
            
        </div>

        <!-- 图片上传组件辅助-->
        <el-upload
            class="avatar-uploader"
            :action="uploadUrl" type="drag"
            :data="prefix"
            :show-file-list="false"
            :on-success="uploadSuccess"
            :on-error="uploadError"
            :before-upload="beforeUpload">
        </el-upload>

        <el-form  label-width="80px">
        <!--富文本编辑器组件-->
            <el-form-item label="上传地址" v-if="upLoadType == 1">
                <el-input clearable placeholder="请输入上传地址" v-model="form.url"></el-input>
            </el-form-item>

            <el-form-item label="上传内容" v-if="upLoadType == 2" v-loading="uillUpdateImg">
                <quill-editor
                    v-model="form.content"
                    ref="myQuillEditor"
                    :options="editorOption"
                    @focus="onEditorFocus($event)"
                    @change="onEditorChange($event)">
                </quill-editor>
            </el-form-item>
        </el-form>

        <el-button type="primary" class="subMit" @click="submitBtn" 
            :disabled="!(Boolean(form.title) && Boolean(form.author) && Boolean(form.cover) && Boolean(form.sort))">提交</el-button>
        <!-- <div class="ql-container ql-snow">
            <div class="ql-editor">
                <div v-html="detailContent"></div>
            </div>
        </div> -->
    </div>
</template>
<script>
    import { subBtnFn, getInfoFn } from 'api/game/find/articleAdd';
    import { toolbarOptions } from 'api/game/find/toolbarOptions'; // 工具栏配置
    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 }, // 注册组件
        data() {
            return {
                uillUpdateImg: false,
                uploadUrl: undefined,
                coverBox: [],
                prefix: {prefix: 'contest'}, // 阿里云额外参数
                upLoadType: 1, // 1为 URL  2为内容
                form: {
                    id: undefined, // 文章id
                    moduleId: undefined, // 模块id
                    title: undefined, // 标题
                    author: undefined, // 作者
                    cover: undefined, // 封面
                    status: 1, // 状态 1:封禁 、2:正常
                    sort: undefined,  // 权重
                    url: undefined,   // 链接地址
                    content: undefined, // 正文内容
                },
                editorOption: {
                    theme: 'snow',  // or 'bubble'
                    modules: {
                        toolbar: {
                            container: toolbarOptions,  // 工具栏
                            handlers: {
                                'image': function (value) {
                                    if (value) {
                                        // 触发input框选择图片文件
                                        document.querySelector('.avatar-uploader input').click()
                                    } else {
                                        this.quill.format('image', false);
                                    }
                                }
                            }
                        }
                    }
                },
            }
        },
        created () {
            this.uploadUrl = this.defaultUploadUrl;
            if (this.$route.query){ // 判断是否有值
                this.form.moduleId = this.$route.query.moduleId;
                if (this.$route.query.id) { // 判断是否为编辑
                    this.form.id = this.$route.query.id;
                    this.getData();
                }
            }
        },
        methods: {
            getData() {
                this.coverBox = []
                getInfoFn({ id: this.form.id }).then(res=>{
                    if (res.code == 0) {
                        this.form = {...res.data};
                        if (res.data.url) { // 1为 URL  2为内容
                            this.upLoadType = 1;
                        } else {
                            this.upLoadType = 2;
                        }
                        this.coverBox.push({url: res.data.cover, name: res.data.cover})
                    } else {
                        this.$message.error( res.message );
                    }
                })
            },

            // 获得焦点事件
            onEditorFocus(e){ this.lenIndex = e.getSelection().index; },
            // 内容改变事件
            onEditorChange(e){ this.lenIndex = e.quill.getSelection().index; },
            escapeStringHTML(str) {  // 转码
                str = str.replace(/</g,'<');
                str = str.replace(/>/g,'>');
                return str;
            },
            /* handleSingleSuccess (res, file) { // res为图片服务器返回的数据
                let quill = this.$refs.myQuillEditor.quill; // 获取富文本组件实例
                if (res.code == '0') {
                    // 插入图片  res.info为服务器返回的图片地址
                    quill.insertEmbed(this.lenIndex, 'image', res.data)
                    // 调整光标到最后
                    quill.setSelection(this.lenIndex + 1)
                } else {
                    this.$message.error('图片插入失败')
                }
                this.quillUpdateImg = false;  // loading动画消失
            }, */


            // 富文本图片上传前
            beforeUpload() { this.quillUpdateImg = true; },
            uploadSuccess(res, file) {  // res为图片服务器返回的数据
                let quill = this.$refs.myQuillEditor.quill;
                if (res.code == 0) {
                    let length = quill.getSelection().index; // 获取光标所在位置
                    quill.insertEmbed(length, 'image', res.data); // 插入图片  res.info为服务器返回的图片地址
                    quill.setSelection(length + 1); // 调整光标到最后
                } else {
                    this.$message.error('图片插入失败')
                }
                this.quillUpdateImg = false; // loading动画消失
            },
            // 富文本图片上传失败
            uploadError() {
                // loading动画消失
                this.quillUpdateImg = false;
                this.$message.error('图片插入失败');
            },
            submitBtn() {
                if (this.upLoadType == 1) { // 1为 URL  2为内容
                    this.form.content = undefined;
                    if (!this.form.url) {
                        this.$message.error({ message: '请填写您要上传的数据!' });
                        return;
                    }
                } else {
                    this.form.url = undefined;
                    if (!this.form.content) {
                        this.$message.error({ message: '请填写您要上传的数据!' });
                        return;
                    }
                }
                subBtnFn({...this.form}).then(res => {
                    if (res.code == 0) {
                        this.$message({ showClose: true, message: '数据添加成功,即将进行跳转', type: 'success' });
                        setTimeout(() => {
                            this.$router.push({
                                path: '/find/articleManage',
                                query:{
                                    copywritingId: this.form.moduleId
                                }
                            });
                        }, 1500);
                    }
                })
            },
            // 封面上传
            handleAvatarSuccess(res, file) { this.form.cover = res.data; },
            handleRemove (file, fileList) { this.edit.cover = ''; },
        },
    }

</script>
<style>
    #articleAdd {
        margin: 30px;
    }

    #articleAdd .avatar-uploader .el-upload {
        border: 1px dashed #d9d9d9;
        border-radius: 6px;
        cursor: pointer;
        position: relative;
        overflow: hidden;
    }
    #articleAdd .avatar-uploader .el-upload:hover {
        border-color: #409EFF;
    }
    #articleAdd .avatar-uploader-icon {
        font-size: 28px;
        color: #8c939d;
        width: 178px;
        height: 178px;
        line-height: 178px;
        text-align: center;
    }
    #articleAdd .avatar {
        width: 178px;
        height: 178px;
        display: block;
    }
    #articleAdd .subMit {
        /* float: right; */
        margin: 20px 0;
    }
</style>

我直接将代码贴过来了, template中的代码应该可以看懂,style中的就不要说了,script中的注释我也写了,如果还是看不懂 可以加我 QQ: 2489757828

个人博客:李大玄

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

推荐阅读更多精彩内容