[前端工程化 - 组件封装]图片上传组件

前言

大家好,我是辉夜真是太可爱啦,这是我即将最新开启的组件封装或基于组件库二次封装系列,代码均以 vue2 为例,组件库以 vant 为栗子

组件的封装在工作中使用的用处还是很大的,主要体现在维护的方便,可以将所有固定的代码抽到同一个组件中进行统一管理。

封装目的

这次是实现的是图片上传的功能,由于 vant 组件的 uploader 组件的 v-model 设计不太合理。

一般来说,正常单张图片的值是一个 String ,例如 https://xxxx.jpg

然后一串图片是一个 Array ,例如 ['https://xxxx.jpg' , 'https://xxxx.jpg']

然后我们仅通过一个 v-model 即可绑定这个值,无需对图片上传之后值的更新,图片删除之后值的清空,或者是默认值的渲染再做多余的管理,可以大大的提升图片相关功能的开发效率。

后期还可以配合写一个 form 组件,使用 json 生成 form 表单。

Props

  • v-model 绑定的图片的值
  • max-count 绑定的最大值,1为单张图,大于1为列表
  • tips 文件上传提示语

Slot

  • defautl 默认插槽,用于修改图片上传的控件

开始封装

先书写 template 板块,关于插槽内的图片上传框的样式请自行修改。

html 复制代码
<template>
  <div class="image-uploader-component-main-box">
    <van-uploader
      :after-read="afterRead"
      :max-size="1024 * 1024 * 10"
      @delete="deleteFile"
      v-model="fileList"
      :max-count="maxCount"
      accept="image/png,image/jpeg,image/jpg"
    >
      <slot>
        <div class="upload-box">
          <span>图片上传</span>
        </div>
      </slot>
    </van-uploader>
  </div>
</template>

接下来,就是封装 js 的部分,由于fileList的格式是固定的,所以接下来需要用一个currentValue来进行绑定,fileList的数组,在初次渲染的时候,需要将currentValue中的值赋值给fileList,这样子才能保持两边数组的同步。

当然,uploadImage 图片上传的调用行为,请自行修改。

javascript 复制代码
<script>
export default {
  name: 'ImageUploader',

  props: {
    value: {
      type: [Array, String],
      default: '',
    },
    maxCount: {
      type: Number,
      default: 1,
    },
  },

  data() {
    return {
      currentValue: this.value,
      fileList: [],
      isInit: false, // 将一开始的默认值赋值给 fileList
    }
  },

  watch: {
    value: {
      handler(newValue) {
        if (!this.isInit) {
          if (this.maxCount === 1) {
            this.fileList = [
              {
                url: newValue,
                status: 'success',
                message: '上传成功',
              },
            ]
          } else {
            newValue.forEach((item) => {
              this.fileList.push({
                url: item,
                status: 'success',
                message: '上传成功',
              })
            })
          }
        }
        this.currentValue = newValue
      },
    },
  },

  methods: {
    afterRead(file) {
      this.isInit = true
      file.status = 'uploading'
      file.message = '上传中...'
      const formData = new FormData()
      formData.append('file', file.file)
      uploadImage(formData)
        .then((res) => {
          if (res.url) {
            file.status = 'success'
            file.message = '上传成功'
            file.url = res // FIXME: 这里上传不做全地址处理了
            if (this.maxCount === 1) {
              this.currentValue = res.url
            } else {
              this.currentValue.push(res.url)
            }
            this.$emit('input', this.currentValue)
          } else {
            file.status = 'failed'
            file.message = '上传失败'
            this.$toast.fail(res.error)
          }
        })
        .catch(() => {
          file.status = 'failed'
          file.message = '上传失败'
        })
    },

    deleteFile(file) {
      if (this.maxCount === 1) {
        this.currentValue = ''
      } else {
        this.currentValue.splice(
          this.currentValue.findIndex((x) => x === file.url),
          1
        )
      }
      this.$emit('input', this.currentValue)
    },
  },
}
</script>

至于另外别的 API,此处不再做多余的赘述,仅仅搬运下即可。

组件使用

  • 单个使用
javascript 复制代码
<ImageUploader v-model="imgUrl"></ImageUploader>

data() {
  return {
    imgUrl: ''
  }
},
  • 多个使用
ruby 复制代码
<ImageUploader v-model="imgList" :max-count="5"></ImageUploader>

data() {
  return {
    imgList: []
  }
},
相关推荐
熊的猫27 分钟前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
瑶琴AI前端1 小时前
uniapp组件实现省市区三级联动选择
java·前端·uni-app
会发光的猪。1 小时前
如何在vscode中安装git详细新手教程
前端·ide·git·vscode
mosen8681 小时前
Uniapp去除顶部导航栏-小程序、H5、APP适用
vue.js·微信小程序·小程序·uni-app·uniapp
别拿曾经看以后~2 小时前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
我要洋人死2 小时前
导航栏及下拉菜单的实现
前端·css·css3
科技探秘人2 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人2 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR2 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香2 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel