【Svelte】怎样实现一个图片上传功能?

在 Svelte 中实现这个功能,最优雅的方式是结合使用 bind:this(获取 input 引用)和 URL.createObjectURL(生成本地预览地址)。

以下是完整的实现代码:

svelte 复制代码
<script>
  // 1. 定义初始默认图片地址
  let imageUrl = "https://example.com/default-cover.png";
  
  // 2. 用于绑定隐藏的 input 元素
  let fileInput;

  // 3. 点击图片时,模拟点击隐藏的 input
  function triggerFileInput() {
    fileInput.click();
  }

  // 4. 处理文件选择逻辑
  function handleFileChange(event) {
    const file = event.target.files[0];
    if (file) {
      // 检查是否是图片类型(可选)
      if (!file.type.startsWith('image/')) {
        alert('请选择图片文件');
        return;
      }

      // 释放之前的内存(如果是通过 createObjectURL 创建的)
      if (imageUrl.startsWith('blob:')) {
        URL.revokeObjectURL(imageUrl);
      }

      // 生成预览 URL 并替换原有图片
      imageUrl = URL.createObjectURL(file);
      
      // 这里可以添加上传到服务器的逻辑,例如使用 FormData 上传
      // uploadToServer(file);
    }
  }
</script>

<div class="upload-container">
  <!-- svelte-ignore a11y-click-events-have-key-events -->
  <!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
  <img 
    src={imageUrl} 
    alt="封面图" 
    class="preview-img"
    on:click={triggerFileInput} 
  />

  <!-- 隐藏的隐藏文件输入框 -->
  <input 
    type="file" 
    accept="image/*" 
    bind:this={fileInput} 
    on:change={handleFileChange} 
    style="display: none;" 
  />
  
  <p class="hint">点击图片更换封面</p>
</div>

<style>
  .upload-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    margin-top: 20px;
  }

  .preview-img {
    width: 300px;         /* 你可以根据需要调整大小 */
    height: 200px;
    object-fit: cover;    /* 保持图片比例 */
    cursor: pointer;      /* 鼠标悬停显示手型 */
    border-radius: 8px;
    border: 2px dashed #ccc;
    transition: opacity 0.2s;
  }

  .preview-img:hover {
    opacity: 0.8;
    border-color: #ff3e00; /* Svelte 橙色 */
  }

  .hint {
    font-size: 14px;
    color: #666;
  }
</style>

关键点解析:

  1. bind:this={fileInput} : 这是 Svelte 获取 DOM 节点引用的方式。通过它,我们可以调用 fileInput.click() 来触发文件选择窗口,而无需在页面上显示丑陋的默认按钮。
  2. URL.createObjectURL(file) : 这是一个浏览器 API,它可以为选中的本地文件创建一个临时的 URL。这样用户选择图片后,图片能立即显示出来,而不需要等待上传到服务器。
  3. accept="image/*": 限制文件选择器只能选择图片文件。
  4. 内存管理 : 代码中加入了 URL.revokeObjectURL(imageUrl)。这是一个好习惯,当预览图被替换时,释放旧的内存占用,防止长久使用导致的页面卡顿。

进阶建议:

如果你需要将图片真正上传到后端服务器 ,可以在 handleFileChange 函数中加入以下逻辑:

javascript 复制代码
async function uploadToServer(file) {
  const formData = new FormData();
  formData.append('file', file);

  const response = await fetch('你的上传接口地址', {
    method: 'POST',
    body: formData
  });
  const result = await response.json();
  // 成功后可以将 imageUrl 替换为后端返回的正式持久化地址
  // imageUrl = result.url;
}
相关推荐
shehuiyuelaiyuehao2 小时前
7类和对象
java·开发语言
心.c2 小时前
为什么在 Vue 3 中 uni.createCanvasContext 画不出图?
前端·javascript·vue.js
落羽的落羽2 小时前
【C++】深入浅出“图”——图的基本概念与存储结构
服务器·开发语言·数据结构·c++·人工智能·机器学习·图搜索算法
bugcome_com2 小时前
C# 中 Overload(重载)与 Override(重写)的核心区别与实战解析
开发语言·c#
咸鱼加辣2 小时前
【vue面试】ref和reactive
前端·javascript·vue.js
LYFlied2 小时前
【每日算法】LeetCode 104. 二叉树的最大深度
前端·算法·leetcode·面试·职场和发展
巴塞罗那的风2 小时前
从蓝图到执行:智能体中的“战略家思维
开发语言·后端·ai·语言模型·golang
宁雨桥2 小时前
前端并发控制的多种实现方案与最佳实践
前端
JAVA+C语言2 小时前
Python新手学习
开发语言·python·学习