提取封面图 URL 的原理和过程

一、提取封面图 URL 的原理和过程

背景:封面图是怎么上传的?

在表单中,你用了 antdUpload 组件来上传封面图:

<Upload
  name="image"
  listType="picture-card"
  action="http://geek.itheima.net/v1_0/upload"
  fileList={fileList}
  onChange={onUploadChange}
  ...
>
  <PlusOutlined />
</Upload>

上传时会自动把图片发给 action 指定的后端地址,后端返回图片地址。你监听 onChange 拿到图片上传的结果。

fileList 长什么样?

它是一个数组,结构类似这样(成功上传后):

[
  {
    url: "http://geek.itheima.net/files/2025/04/cover1.png"
  },
  {
    url: "http://geek.itheima.net/files/2025/04/cover2.png"
  },
  ...
]

这些 url 就是上传后返回的图片地址,你可以直接提交给后端。

fileList 是怎么被处理成这个样子的?

看看这个函数:

const cacheImgList = useRef() // 缓存图片,用于封面图切换回显


const onUploadChange = ({ fileList }) => {
  const formatList = fileList.map(file => {
    // 上传完毕 做数据处理
    if (file.response) {
      // 上传完成后,提取后端返回的图片 URL
      return {
        url: file.response.data.url
      }
    }
    // 否则在上传中时,不做处理
    return file
  })

  setFileList(formatList)
   // 同时把图片列表存入仓库一份
  cacheImgList.current = formatList // 存入缓存
  // 作用:在图片上传成功后,把完整的图片列表存一份“缓存”,用于后续切换封面图数量时做“图像恢复”。
}

关键点解释:

  • 当你上传图片后,后端会返回一个 JSON 响应:

{
  "data": {
    "url": "http://geek.itheima.net/files/cover123.jpg"
  }
}
  • file.response.data.url 就是这个地址。

  • fileList.map(...) 处理后,我们只保留图片的 url 字段,变成一个非常干净的数组。

那提取封面图的时候是怎么做的?

onFinish 提交时的代码:

  // 获取表单数据
  const onFinish = async(values) =>{ 
    // 数据的二次处理 重点是处理cover字段
    const { channel_id, content, title, type } = values

    // 判断type fileList 是匹配的才能正常提交
    const params = {
      channel_id,
      content,
      title,
      type,
      cover: {
        type: type,
        images: fileList.map(item => item.url)
      }
    }

    if (id) {
      // ?draft=false:表示不是草稿状态,是直接“发布”的。
      await http.put(`/mp/articles/${id}?draft=false`, params)
    } else {
      await http.post('/mp/articles?draft=false', params)
    }
    /*
        这段逻辑是用来实现 “一页双用” 的:
        没有 id 就走新增文章接口;
        有 id 就走更新文章接口。
        让发布和编辑共用同一个页面,效率高又方便管理。

        params:是你前面收集好的表单数据,结构大致是这样
        {
          channel_id,
          content,
          title,
          type,
          cover: {
            type,
          images: [...]
          }
        }

    */
 
    // 跳转列表 提示用户
    navigate('/layout/article')
    message.success(`${id ? '更新成功' : '发布成功'}`)
  }

就是把 fileList 里的每一项的 url 提取出来,组成一个图片地址数组:

images: [
  "http://geek.itheima.net/files/cover1.jpg",
  "http://geek.itheima.net/files/cover2.jpg"
]

这些数据会一起发送给后端,保存为文章封面图。

二、如果想切换一图或者三图的功能

const radioChange = (e) =>{ 
    const rawValue = e.target.value
    setImgCount(rawValue)
    console.log(cacheImgList.current);
    // 从仓库里面获取对应的图片数量 交给用来渲染图片的fileList
    if(cacheImgList.current === undefined || 0){
      return false
    }
    if( rawValue === 1 ){
      const img = cacheImgList.current ? cacheImgList.current[0] : []
      setFileList([img])
    }else if ( rawValue === 3 ){
      setFileList(cacheImgList.current)
    }
  }


.....

<Item label="封面">
    <Item name="type">
              <Radio.Group onChange={radioChange}>
                <Radio value={1}>单图</Radio>
                <Radio value={3}>三图</Radio>
                <Radio value={0}>无图</Radio>
              </Radio.Group>
     </Item>

     { imgCount > 0 && (
     <Upload name='image' listType='picture-card' className='avatar-uploader' showUploadList action="http://geek.itheima.net/v1_0/upload" fileList={fileList} onChange={onUploadChange} multiple={ imgCount > 1 } maxCount={ imgCount } >
                <div style={{marginTop:8}}>
                  <PlusOutlined />
                </div>
      </Upload>)
     }
  
</Item>
         

cacheImgList 是干什么的?

  • fileList正在显示的图片列表,用于 <Upload /> 显示当前上传的图片。

  • cacheImgList.current缓存所有上传过的图片,不管当前是否显示。

比如你上传了 3 张图,然后你选择“单图” → 只显示 1 张
再切回“三图” → 你希望还能看到之前上传的 3 张图!

所以我们在上传时就缓存一份完整列表,以便随时恢复。

举个真实例子

用户流程如下:

  1. 选择 “三图”

  2. 上传了 3 张图
    👉 此时:
    fileList = [图1, 图2, 图3]
    cacheImgList.current = [图1, 图2, 图3]

  3. 用户切换到 “单图” 👉 代码只显示 fileList = [图1]

  4. 用户切回 “三图” 👉 从 cacheImgList.current 恢复出 [图1, 图2, 图3]

如果你不缓存,之前上传的图就“丢了”,只能重新上传,非常影响体验。

为什么用 useRef

因为我们不需要触发组件重新渲染,仅仅是临时存储一些数据,这时候就推荐用 useRef

const cacheImgList = useRef() // 相当于一个组件内的变量

比用 useState 更轻量,也不会引起重复渲染。

cacheImgList.current = formatList

作用:在图片上传成功后,把完整的图片列表存一份“缓存”,用于后续切换封面图数量时做“图像恢复”。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值