Vue3+ElementPlus 封装图片空间组件的门面

什么是图片空间?
图片空间就是专门管理我们上传图片的地方。就好比用户管理一样,我们对要上传的图片进行管理。
这样做的好处有哪些?
我们把可能需要的图片都上传到图片管理中。在其他需要图片的地方(如:商品图片等)可以直接调用图片空间组件,从图片空间中进行选择。
图片空间的样式多种多样,但是它们的入口都是一样的,所以这里封装了图片空间的门面。

  1. PictureSpaceFacade.vue 组件
<script setup>
const props=defineProps({
  // 图片数组或字符串(http://a.com/1.jpg,http://a.com/2.jpg 用逗号隔开)
  modelValue: {
    type: [Array,String,Object],
  },
  // 图片宽度
  pictureWidth: {
    type:String,
    default: '100px'
  },
  // 图片高度
  pictureHeight:{
    type:String,
    default: '100px'
  }
})

const emits=defineEmits(['update:modelValue'])

import {ref, watch} from "vue";

// 图片数组
const pictureList = ref([])

// 监听props.modelValue变化
watch(() => props.modelValue, (newValue) => {
  if (newValue){
    pictureList.value=Array.isArray(newValue) ? newValue : props.modelValue.split(",");
  }else{
    pictureList.value = []
  }
},{deep:true,immediate:true})

// 预览图片开关
const previewVisible = ref(false)
// 预览图片url
const previewImageUrl = ref('')
// 点击预览图片按钮回调
function previewPicture(url) {
  previewVisible.value = true
  previewImageUrl.value = url
}
// 点击删除图片按钮回调
function deletePicture(url) {
  pictureList.value = pictureList.value.filter(item => url !== item)
  emits('update:modelValue', pictureList.value)
}

</script>

<template>
  <div id="app">
    <div class="container">
      <div class="container-item" :style="{width:pictureWidth ,height:pictureHeight}" v-for="item in pictureList" :key="item">
        <img class="img-item" :src="item" alt=""/>
        <div class="overlay">
          <span class="opt" @click="previewPicture(item)">预览</span>
          <span class="opt" @click="deletePicture(item)">删除</span>
        </div>
      </div>
      <div class="container-item add-container" :style="{width:pictureWidth ,height:pictureHeight}">
        <slot>+</slot>
      </div>
    </div>

    <!--    图片预览-->
    <el-dialog v-model="previewVisible" style="overflow: auto">
      <div style="height: 100%; width: 100%; display: flex; justify-content: center; align-items: center;">
        <img style="object-fit: cover; height: 100%; width: 100%;" :src="previewImageUrl" alt="Preview Image"/>
      </div>
    </el-dialog>

  </div>
</template>

<style scoped lang="scss">

.container {
  display: flex;
  flex-wrap: wrap;
  width: 100%;
}

.container-item {
  height: 150px;
  width: 150px;
  margin: 3px;
  border: 1px solid #cecaca;
  border-radius: 5px;
  overflow: hidden;
  position: relative;

  &:hover .overlay {
    opacity: 1;
  }

  .img-item {
    height: 100%;
    width: 100%;
  }

  .overlay {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    color: #fff;
    font-size: 14px;
    opacity: 0;
    transition: opacity .5s;

    .opt {
      cursor: pointer;
      margin: 8px;
    }
  }
}

.add-container {
  border: 1px dashed #cecaca;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;

  &:hover {
    border: 1px dashed blue;
  }
}
</style>

PictureSpaceFacade 组件使用:

<script setup>
import {ref} from "vue";
import PictureSpaceFacade from "./components/PictureSpaceFacade.vue";

// 获取随机图片
async function getPicture() {
  const response = await fetch('https://dog.ceo/api/breeds/image/random')
  const res = await response.json()
  return res.message
}

// 图片数组
const pictureList = ref([])
// 初始化图片数组(准备测试数据)
async function initPicture() {
  for (let i = 0; i < 3; i++) {
    pictureList.value.push(await getPicture())
  }
}

// 图片空间开关
const pictureSpaceVisible = ref(false)

// 打开图片空间
function openPictureSpace() {
  pictureSpaceVisible.value = true
}

// 关闭图片空间(从图片空间选择图片后对 pictureList进行填充)
async function closePictureSpace() {
  for (let i = 0; i < 2; i++) {
    pictureList.value.push(await getPicture())
  }
  pictureSpaceVisible.value = false
}

initPicture()
</script>

<template>
  <el-row>
    <el-col :span="8">
      <PictureSpaceFacade v-model="pictureList" width="220px" picture-width="100px" picture-height="100px">
        <div style="height: 100%;width: 100%;display: flex;justify-content: center;align-items: center;"
             @click="openPictureSpace">+
        </div>
      </PictureSpaceFacade>
    </el-col>
  </el-row>

  <!--  图片空间弹出框-->
  <el-dialog v-model="pictureSpaceVisible" title="图片空间" @close="closePictureSpace">

  </el-dialog>
</template>

<style scoped lang="scss">

</style>

  1. 图片宽度和高度就是图片自身。
  2. 鼠标悬浮会出现操作按钮(这里的文字可以自行修改为icon图标)。
    在这里插入图片描述
  3. 点击图片添加框,会弹出图片空间组件供我们选择。我们通过选项绑定将pcitureList存入图片空间,这样在图片空间中就能够修改我们的图片数组。

在这里插入图片描述

你可以尝试以下步骤来封装一个Vue 3和TypeScript下使用Element Plus的表单提交组件: 1. 安装必要的依赖: - Vue 3:`npm install vue@next` - TypeScript:`npm install -D typescript` - Element Plus:`npm install element-plus` 2. 创建一个新的Vue组件,并为其选择一个合适的名称,例如`FormSubmit.vue`。 3. 在`FormSubmit.vue`文件中,导入必要的模块和样式: ```vue <template> <!-- 表单内容 --> </template> <script lang="ts"> import { defineComponent } from 'vue'; import { ElButton, ElForm, ElFormItem } from 'element-plus'; export default defineComponent({ components: { ElButton, ElForm, ElFormItem, }, }); </script> <style scoped> /* Element Plus 样式 */ @import 'element-plus/packages/theme-chalk/src/index.scss'; /* 自定义样式 */ /* ... */ </style> ``` 4. 在模板中编写表单内容,并使用Element Plus的组件来构建表单: ```vue <template> <el-form ref="form" :model="formData" label-width="120px"> <el-form-item label="姓名" prop="name"> <el-input v-model="formData.name"></el-input> </el-form-item> <!-- 更多表单项 --> <el-form-item> <el-button type="primary" @click="submitForm">提交</el-button> </el-form-item> </el-form> </template> <script lang="ts"> // ... export default defineComponent({ // ... data() { return { formData: { name: '', // 更多表单字段 } }; }, methods: { submitForm() { // 表单提交逻辑 if (this.$refs.form.validate()) { // 表单验证通过,执行提交操作 // ... } } } }); </script> ``` 这样,你就可以使用封装好的表单提交组件来方便地处理表单提交了。你可以根据实际需求添加更多的表单项,并在`submitForm`方法中实现你的提交逻辑。希望这可以帮到你!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值