vue+element上传图片

一、html页面上传图片

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div>
        <input type="file" id="fileInput" />
        <img id="imagePreview" src="" alt="Image Preview" />
    </div>
</body>
</html>
<script>
    const fileInput = document.getElementById('fileInput');
    const imagePreview = document.getElementById('imagePreview');
    
    fileInput.addEventListener('change', (event) => {
      // 获取用户选择的第一个文件
      const file = event.target.files[0]; 
      if (file) {
        const objectURL = URL.createObjectURL(file); // 创建临时 URL
        imagePreview.src = objectURL; // 设置为 img 标签的 src
      }
    });
</script>

二、vue选择图片和上传图片

1.:auto-upload="false"取消自动上传,点击上传头像按钮上传

2.:on-change文件上传成功时的钩子,(选择图片后,把图片格式转换为base64格式)

3.点击button按钮和upload组件都可以选择图片

4.上传图片(发送请求更新头像,userStore重新更新数据,给用户提示)

html 复制代码
<template>
  <PageContainer title="更换头像">
    <el-upload
      ref="uploadRef"
      class="avatar-uploader"
      :auto-upload="false"
      :show-file-list="false"
      :before-upload="beforeAvatarUpload"
      :on-change="onSelectFile"
    >
      <img v-if="imageUrl" :src="imageUrl" class="avatar" />
      <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
    </el-upload>
    <div class="btns">
      <el-button icon="Plus" type="primary" @click="onSelectFn"
        >选择图片</el-button
      >
      <el-button icon="Upload" type="success" @click="onUpdateFn"
        >上传头像</el-button
      >
    </div>
  </PageContainer>
</template>
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { Plus, Upload } from "@element-plus/icons-vue";
import PageContainer from "@/components/PageContainer.vue";
import { updateAvatarApi } from "@/api/user";
import { useUserStore } from "@/store";
//基于store的数据拿到imageUrl的初始值
const userStore = useUserStore();
//图片上传
const imageUrl = ref(userStore.userInfo.user_pic);
const uploadRef = ref();
const beforeAvatarUpload = (rawFile) => {
  if (rawFile.type !== "image/jpeg") {
    ElMessage.error("Avatar picture must be JPG format!");
    return false;
  } else if (rawFile.size / 1024 / 1024 > 2) {
    ElMessage.error("Avatar picture size can not exceed 2MB!");
    return false;
  }
  return true;
};
const onSelectFile = (uploadFile) => {
  //基于fileReader读取图片做预览
  const reader = new FileReader();
  // 将文件读入为Data URL
  reader.readAsDataURL(uploadFile.raw);
  // 获取Base64字符串
  reader.onload = () => {
    imageUrl.value = reader.result;
  };
};
const onSelectFn = () => {
  uploadRef.value.$el.querySelector("input").click();
};
const onUpdateFn = async () => {
  //发送请求更新头像
  await updateAvatarApi(imageUrl.value);
  //userStore重新渲染
  await userStore.getuserInfo();
  //提示用户
  ElMessage.success("修改成功");
};
</script>
<style lang="scss">
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}
.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}
.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
.btns {
  margin-top: 20px;
}
</style>

三、表单中上传图片

1.在表单中使用upload组件

2.URL.createObjectURL 是一个在 JavaScript 中用于创建一个指向 BlobFile 对象的临时 URL 的方法。这种方法非常有用,尤其是在处理文件上传或生成动态内容时,比如图像预览。imageUrl.value = URL.createObjectURL(uploadFile.raw);

  1. 生成临时 URL : 它为 BlobFile 对象生成一个可以在浏览器中使用的 URL。这个 URL 是临时的,仅在页面生命周期内有效。

  2. 文件预览 : 在用户选择文件后,可以使用这个 URL 显示图像预览。比如,当用户上传一张图片时,可以生成这个 URL 并将其设置为 <img> 标签的 src 属性。

3.使用 Axios 来获取网络图片并将其转换为 File 对象。以下是具体的实现步骤:

  1. 使用 Axios 请求获取图片的 Blob 数据。
  2. 将 Blob 数据转换为 File 对象。
html 复制代码
<template>
  <el-drawer v-model="drawerVisible" direction="rtl">
    <template #header>
      <h4>{{ formModel.id ? "编辑文章" : "添加文章" }}</h4>
    </template>
    <template #default>
      <el-form :model="formModel" :rules="rules" ref="formRef">
        <el-form-item label="文章标题" prop="title">
          <el-input v-model="formModel.title"></el-input>
        </el-form-item>
        <el-form-item label="文章分类" props="cate_id">
          <ChannelSelect
            v-model:modelValue="formModel.cate_id"
            width="100%"
          ></ChannelSelect>
        </el-form-item>
        <el-form-item label="文章封面" prop="cover_img">
          <el-upload
            class="avatar-uploader"
            :auto-upload="false"
            :show-file-list="false"
            :before-upload="beforeAvatarUpload"
            :on-change="onSelectFile"
          >
            <img v-if="imageUrl" :src="imageUrl" class="avatar" />
            <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
          </el-upload>
        </el-form-item>
        <el-form-item label="文章内容" prop="content">
          <div class="editor">
            <QuillEditor
              ref="editorRef"
              v-model:content="formModel.content"
              theme="snow"
              contentType="html"
            />
          </div>
        </el-form-item>
        <el-form-item label=" ">
          <div>
            <el-button type="primary" @click="onPublisg('已发布')"
              >发布</el-button
            >
            <el-button @click="onPublisg('草稿')">草稿</el-button>
          </div>
        </el-form-item>
      </el-form>
    </template>
  </el-drawer>
</template>
<script setup>
import { ref, nextTick } from "vue";
import ChannelSelect from "@/view/article/component/ChannelSelect.vue";
import {
  addArticlePublishApi,
  getArticleInfoApi,
  editArticleInfoApi,
} from "@/api/article.js";
import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { ElMessage } from "element-plus";
import { baseURL } from "@/utils/request";
const drawerVisible = ref(false);
const emit = defineEmits(["success"]);
const deaultFormModel = {
  title: "",
  cate_id: "",
  cover_img: "",
  content: "",
  state: "",
};
const formModel = ref({ ...deaultFormModel });
const formRef = ref();
const editorRef = ref();
const open = async (row) => {
  drawerVisible.value = true;
  if (row.id) {
    const res = await getArticleInfoApi(row.id);
    formModel.value = res.data.data;
    console.log(res);
    imageUrl.value = `${baseURL}${res.data.data.cover_img}`;
    //提交给后台需要的格式是file格式对象,需要将网络图片地址转为file对象,将 File 对象赋值给表单模型
    const file = await convertImageUrlToFile(
      imageUrl,
      formModel.value.cover_img
    );
    formModel.value.cover_img = file;
  } else {
    formModel.value = { ...deaultFormModel };
    console.log("editorRef.value", editorRef.value);
    imageUrl.value = "";
    await nextTick(() => {
      editorRef.value.setHTML("");
    });
  }
};
defineExpose({ open });
//图片上传
const imageUrl = ref("");
const beforeAvatarUpload = (rawFile) => {
  if (rawFile.type !== "image/jpeg") {
    ElMessage.error("Avatar picture must be JPG format!");
    return false;
  } else if (rawFile.size / 1024 / 1024 > 2) {
    ElMessage.error("Avatar picture size can not exceed 2MB!");
    return false;
  }
  return true;
};
const onSelectFile = (uploadFile) => {
  imageUrl.value = URL.createObjectURL(uploadFile.raw);
  formModel.value.cover_img = uploadFile.raw;
};
const onPublisg = async (state) => {
  formModel.value.state = state;
  const fd = new FormData();
  for (let key in formModel.value) {
    fd.append(key, formModel.value[key]);
  }
  if (formModel.value.id) {
    await editArticleInfoApi(fd);
    ElMessage.success("修改成功");
    drawerVisible.value = false;
    emit("success", "emit");
  } else {
    await addArticlePublishApi(fd);
    ElMessage.success("添加成功");
    drawerVisible.value = false;
    console.log("drawerVisible.value", drawerVisible.value);
    emit("success", "add");
  }
};
const convertImageUrlToFile = async (imageUrl, fileName = "image.jpg") => {
  // 使用 Axios 获取图片
  const response = await axios.get(imageUrl, {
    responseType: "blob", // 设置响应类型为 blob
  });
  // 创建 File 对象
  const file = new File([response.data], fileName, {
    type: response.data.type,
  });
  return file;
};
</script>
<style lang="scss" scoped>
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
.editor {
  width: 100%;
  .ql-editor {
    min-height: 200px !important;
  }
}
</style>
相关推荐
IT女孩儿1 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡2 小时前
commitlint校验git提交信息
前端
天天进步20152 小时前
Vue+Springboot用Websocket实现协同编辑
vue.js·spring boot·websocket
虾球xz2 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇3 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒3 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员3 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js
野槐3 小时前
前端图像处理(一)
前端
程序猿阿伟3 小时前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
疯狂的沙粒3 小时前
对 TypeScript 中函数如何更好的理解及使用?与 JavaScript 函数有哪些区别?
前端·javascript·typescript