• Vant React

Uploader 文件上传

介绍

用于将本地的图片或文件上传至服务器,并在上传过程中展示预览图。目前 Uploader 组件不包含将文件上传至服务器的接口逻辑,该步骤需要自行实现。

引入

import { Uploader } from "taroify/core"

代码演示

基础用法

文件上传触发 onUpload 事件,获取到对应的 file 对象。

function BasicUploader() {
  const [file, setFile] = useState<Uploader.File>()

  function onUpload() {
    chooseImage({
      count: 1,
      sizeType: ["original", "compressed"],
      sourceType: ["album", "camera"],
    }).then(({ tempFiles }) => {
      setFile({
        url: tempFiles[0].path,
        type: tempFiles[0].type,
        name: tempFiles[0].originalFileObj?.name,
      })
    })
  }

  return <Uploader value={file} onUpload={onUpload} onChange={setFile} />
}

文件预览

通过 value 属性可以绑定已经上传的文件列表,并展示文件列表的预览图。

function PreviewUploader() {
  const [files, setFiles] = useState<Uploader.File[]>([
    {
      url: "https://img01.yzcdn.cn/vant/leaf.jpg",
    },
    {
      url: "https://img.yzcdn.cn/vant/tree.jpg",
    },
  ])

  function onUpload() {
    chooseImage({
      count: 1,
      sizeType: ["original", "compressed"],
      sourceType: ["album", "camera"],
    }).then(({ tempFiles }) => {
      setFiles([
        ...files,
        ...tempFiles.map(({ path, type, originalFileObj }) => ({
          type,
          url: path,
          name: originalFileObj?.name,
        })),
      ])
    })
  }

  return <Uploader value={files} multiple onUpload={onUpload} onChange={setFiles} />
}

上传状态

通过 status 属性可以标识上传状态,uploading 表示上传中,failed 表示上传失败,completed 表示上传完成。

function UploaderWithStatus() {
  const [files, setFiles] = useState<Uploader.File[]>([
    {
      url: "https://img01.yzcdn.cn/vant/leaf.jpg",
      status: "uploading",
      message: "上传中...",
    },
    {
      url: "https://img01.yzcdn.cn/vant/tree.jpg",
      status: "failed",
      message: "上传失败",
    },
  ])

  function onUpload() {
    chooseImage({
      count: 1,
      sizeType: ["original", "compressed"],
      sourceType: ["album", "camera"],
    }).then(({ tempFiles }) => {
      setFiles([
        ...files,
        ...tempFiles.map(({ path, type, originalFileObj }) => ({
          type,
          url: path,
          name: originalFileObj?.name,
        })),
      ])
    })
  }

  return <Uploader value={files} multiple onUpload={onUpload} onChange={setFiles} />
}

限制上传数量

通过 maxFiles 属性可以限制上传文件的数量,上传数量达到限制后,会自动隐藏上传区域。

function MaxFilesUploader() {
  const [files, setFiles] = useState<Uploader.File[]>([])

  function onUpload() {
    chooseImage({
      count: 1,
      sizeType: ["original", "compressed"],
      sourceType: ["album", "camera"],
    }).then(({ tempFiles }) => {
      setFiles([
        ...files,
        ...tempFiles.map(({ path, type, originalFileObj }) => ({
          type,
          url: path,
          name: originalFileObj?.name,
        })),
      ])
    })
  }

  return <Uploader value={files} multiple maxFiles={2} onUpload={onUpload} onChange={setFiles} />
}

自定义上传样式

通过children可以自定义上传区域的样式。

function CustomUploader() {
  const [files, setFiles] = useState<Uploader.File[]>([])
  function onUpload() {
    chooseImage({
      count: 1,
      sizeType: ["original", "compressed"],
      sourceType: ["album", "camera"],
    }).then(({ tempFiles }) => {
      setFiles([
        ...files,
        ...tempFiles.map(({ path, type, originalFileObj }) => ({
          type,
          url: path,
          name: originalFileObj?.name,
        })),
      ])
    })
  }
  return (
    <Uploader multiple value={files} onChange={setFiles} onUpload={onUpload}>
      <Button icon={<Plus />} color="primary">
        上传文件
      </Button>
    </Uploader>
  )
}

自定义预览样式

通过自定义 Uploader.Image 组件可以自定义覆盖在预览区域上方的内容。
通过 Uploader.Upload 组件触发onUpload

function CustomPreviewUploader() {
  const [files, setFiles] = useState<Uploader.File[]>([
    {
      url: "https://img01.yzcdn.cn/vant/leaf.jpg",
    },
  ])

  function onUpload() {
    chooseImage({
      sizeType: ["original", "compressed"],
      sourceType: ["album", "camera"],
    }).then(({ tempFiles }) => {
      setFiles([
        ...files,
        ...tempFiles.map(({ path, type, originalFileObj }) => ({
          type,
          url: path,
          name: originalFileObj?.name,
        })),
      ])
    })
  }

  return (
    <Uploader value={files} multiple onUpload={onUpload} onChange={setFiles}>
      {files.map((image) => (
        <Uploader.Image
          key={image.url}
          url={image.url}
          name={image.name}
          type={image.type}
          onRemove={() => setFiles(files.filter((item) => item !== image))}
        >
          <View className="preview-cover taroify-ellipsis">图片名称</View>
        </Uploader.Image>
      ))}
      <Uploader.Upload />
    </Uploader>
  )
}
.preview-cover {
  position: absolute;
  bottom: 0;
  box-sizing: border-box;
  width: 100%;
  padding: 4px * 2;
  color: #fff;
  font-size: 12px * 2;
  text-align: center;
  background: rgba(0, 0, 0, 0.3);
}

禁用文件上传

通过 disabled 属性禁用文件上传。

<Uploader disabled />

API

Props

参数说明类型默认值
defaultValue默认已上传的文件列表UploadFile[]-
value已上传的文件列表UploadFile[]-
name标识符,可以在回调函数的第二项参数中获取number | string-
multiple是否开启图片多选,部分安卓机型不支持booleanfalse
disabled是否禁用文件上传booleanfalse
readonly是否将上传区域设置为只读状态booleanfalse
removable是否展示删除按钮booleantrue
maxFiles文件上传数量限制number | string-

Events

事件名说明回调参数
onUpload点击上传区域时触发event: ITouchEvent
onChange已上传图片列表改变后触发file: UploadFile | UploadFile[]

UploadFile

参数说明类型
url下载地址string
type文件类型(包含image时显示图标,其他显示)string
name文件名称string
removable是否可删除boolean
status上传状态(uploadingfailed
messageuploadingfailed 状态时文字提示

主题定制

样式变量

组件提供了下列 CSS 变量,可用于自定义样式,使用方法请参考 ConfigProvider 组件。

名称默认值描述
—uploader-size80px * $hd-
—uploader-disabled-opacityvar(—disabled-opacity)-
—uploader-upload-sizevar(—uploader-size)-
—uploader-upload-widthvar(—uploader-upload-size)-
—uploader-upload-heightvar(—uploader-upload-size)-
—uploader-upload-margin0 var(—padding-xs) var(—padding-xs) 0-
—uploader-upload-background-colorvar(—gray-1)-
—uploader-upload-active-background-colorvar(—active-color)-
—uploader-upload-icon-colorvar(—gray-4)-
—uploader-upload-icon-font-size24px * $hd-
—uploader-upload-text-margin-topvar(—padding-xs)-
—uploader-upload-text-colorvar(—gray-6)-
—uploader-upload-text-font-sizevar(—font-size-sm)-
—uploader-preview-margin0 var(—padding-xs) var(—padding-xs) 0-
—uploader-preview-image-sizevar(—uploader-size)-
—uploader-preview-image-widthvar(—uploader-preview-image-size)-
—uploader-preview-image-heightvar(—uploader-preview-image-size)-
—uploader-remove-size14px * $hd-
—uploader-remove-widthvar(—uploader-remove-size)-
—uploader-remove-heightvar(—uploader-remove-size)-
—uploader-remove-background-colorrgba(0, 0, 0, 0.7)-
—uploader-remove-border-radius0 0 0 12px * $hd-
—uploader-remove-icon-font-size16px * $hd-
—uploader-remove-icon-colorvar(—white)-
—uploader-file-sizevar(—uploader-size)-
—uploader-file-widthvar(—uploader-file-size)-
—uploader-file-heightvar(—uploader-file-size)-
—uploader-file-background-colorvar(—background-color)-
—uploader-file-icon-font-size20px * $hd-
—uploader-file-icon-colorvar(—gray-7)-
—uploader-file-name-padding0 var(—padding-base)-
—uploader-file-name-margin-topvar(—padding-xs)-
—uploader-file-name-font-sizevar(—font-size-sm)-
—uploader-file-name-colorvar(—gray-7)-
—uploader-mask-colorvar(—white)-
—uploader-mask-background-colorrgba(50, 50, 51, 0.88)-
—uploader-mask-icon-size22px * $hd-
—uploader-mask-message-margin-top6px * $hd-
—uploader-mask-message-padding0 var(—padding-base)-
—uploader-mask-message-font-sizevar(—font-size-sm)-
—uploader-mask-message-line-heightvar(—line-height-xs)-
—uploader-loading-icon-size22px * $hd-
—uploader-loading-icon-widthvar(—uploader-loading-icon-size)-
—uploader-loading-icon-heightvar(—uploader-loading-icon-size)-
—uploader-loading-icon-colorvar(—white)-