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

前言

大家好,我是辉夜真是太可爱啦,这是我即将最新开启的组件封装或基于组件库二次封装系列,代码均以 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: []
  }
},
相关推荐
翻滚吧键盘2 分钟前
vue绑定一个返回对象的计算属性
前端·javascript·vue.js
秃了也弱了。20 分钟前
Chrome谷歌浏览器插件ModHeader,修改请求头,开发神器
前端·chrome
乆夨(jiuze)41 分钟前
记录H5内嵌到flutter App的一个问题,引发后面使用fastClick,引发后面input输入框单击无效问题。。。
前端·javascript·vue.js
忧郁的蛋~1 小时前
HTML表格导出为Excel文件的实现方案
前端·html·excel
小彭努力中1 小时前
141.在 Vue 3 中使用 OpenLayers Link 交互:把地图中心点 / 缩放级别 / 旋转角度实时写进 URL,并同步解析显示
前端·javascript·vue.js·交互
然我1 小时前
别再只用 base64!HTML5 的 Blob 才是二进制处理的王者,面试常考
前端·面试·html
NanLing1 小时前
【纯前端推理】纯端侧 AI 对象检测:用浏览器就能跑的深度学习模型
前端
呆呆的心1 小时前
前端必学:从盒模型到定位,一篇搞定页面布局核心 🧩
前端·css
小飞悟1 小时前
前端高手才知道的秘密:Blob 居然这么强大!
前端·javascript·html
小old弟1 小时前
用Sass循环实现炫彩文字跑马灯效果
前端