基于Ant Design of Vue的粗糙组件封装-图片预览

效果图

需求

图片列表显示,并且能够点击图片跳出预览模式,并且能够直接切换查看。

分析

  1. 列表形式的展示图片,可以使用antd Vue的List列表组件和Card卡片
  2. 图片的点击预览可以使用第三方的图片预览组件viewerjs

组件完整代码

/**
* @description GImagePreview.vue 图片预览组件
* @author JUN - 2023/10/19 15:44
*/
<template>
    <a-list :grid="{ gutter: 16,column:columnCount}" :data-source="getAllImages">
        <a-list-item slot="renderItem" slot-scope="{fileName,filePath},index">
            <a-card hoverable
                    size="small"
                    v-show="index<maxCount||maxCount<0"
                    @click="onclick(`image_${index}`)">
                <div slot="cover" class="overflow-hidden bg-gray-100" style="height: 200px;">
                    <div class="w-full h-full imageBox">
                        <img :title="fileName" :src="filePath" :alt="fileName" :ref="`image_${index}`"/>
                    </div>
                </div>
                <a-card-meta class="text-center h-6" :title="fileName"></a-card-meta>
            </a-card>

            <a-card v-show="index===maxCount&&maxCount>-1"
                    hoverable
                    size="small"
                    @click="onclick(`image_${index}`)">
                <div slot="cover" class="overflow-hidden bg-gray-100 text-3xl font-medium" style="height: 200px;">
                    <div class="text-center" style="margin: 40% 0;">
                        <a-icon type="plus"></a-icon>
                        {{ allImages.length - maxCount }}
                    </div>
                </div>
                <a-card-meta class="text-center h-6" title="查看更多"></a-card-meta>
            </a-card>
        </a-list-item>
    </a-list>
</template>

<script lang="ts">
import {
    Vue, Component, Prop, Watch,
} from 'vue-property-decorator';
import $ from 'jquery';
import 'imageviewer/dist/viewer.js';
import 'imageviewer/dist/viewer.css';

/* 被预览的image的数据type */
export type imagePreviewItem = {
    fileName: string;
    filePath: string;
}

@Component({
    name: 'GImagePreview',
})
export default class GImagePreview extends Vue {
    /* 需要展示的图片集合 */
    @Prop({
        type: Array,
        default: () => ([]),
    }) images: imagePreviewItem[] | undefined;

    /* 最多显示的图片数量 */
    @Prop({
        type: Number,
        default: 6,
    }) maxCount: number | undefined;

    /* 是否是本地文件(要对图片路径进行处理) */
    @Prop({
        type: Boolean,
        default: false,
    }) isLocal: boolean | undefined;

    /* 源文件位置(对图片路径进行处理时使用) */
    @Prop({
        type: String,
        default: '',
    }) fileResourceUrl: string | undefined;

    /* 是否显示每个文件名称 */
    @Prop({
        type: Boolean,
        default: false,
    }) isShowFileName: boolean | undefined;

    /* 一行展示多少图片 */
    @Prop({
        type: Number,
        default: 3,
    }) columnCount: number | undefined;

    allImages: any = [];

    /**
     * @description 点击card触发的事件回调(间接利用trigger触发需要预览的image的click事件)
     * @param refName image的ref
     * @return void
     * @author JUN - 2023/10/19 15:37
     */
    onclick(refName) {
        const image_ref = this.$refs[refName];
        if (image_ref) {
            $(image_ref)
                .trigger('click');
        }
    }

    /**
     * @description 格式化一下image的路径
     * @return void
     * @author JUN - 2023/10/19 15:39
     */
    get getAllImages() {
        if (this.isLocal) {
            this.allImages = (this.images || []).map((item) => {
                let { filePath } = item;
                filePath = `${process.env.VUE_APP_API_URL}/images/${filePath}`;
                return {
                    ...item,
                    filePath,
                };
            });
        } else if (this.fileResourceUrl) {
            this.allImages = (this.images || []).map((item) => {
                let { filePath } = item;
                filePath = `${this.fileResourceUrl}${filePath}`;
                return {
                    ...item,
                    filePath,
                };
            });
        } else {
            this.allImages = this.images || [];
        }
        return this.allImages;
    }

    @Watch('images', {
        deep: true,
        immediate: true,
    })
    handleImagesChange(newVal, oldVal) {
        // 这个判断其实没有用,但是为了好看就这样写(总是true)
        if (newVal !== oldVal) {
            ($(this.$el) as any).viewer('destroy');

            this.$nextTick(() => {
                ($(this.$el) as any)
                    .viewer();
            });
        }
    }
}
</script>

<style scoped lang="less">
/deep/ .ant-card-cover {
  .imageBox {
    &:hover {
      transform: scale(1.2);
      transition: all 500ms ease;
    }
  }
}
</style>

使用

使用方式

<g-image-preview :is-show-file-name="true" :images="imageList"></g-image-preview>

图片数据

let imageList=[
  {
    "fileName": "test1.jpeg",
    "filePath": "http://192.168.1.65:9006/directory/item/test1.jpeg?path=test&preview=1&key=default"
  },
  {
    "fileName": "test10.jpg",
    "filePath": "http://192.168.1.65:9006/directory/item/test10.jpg?path=test&preview=1&key=default"
  },
  {
    "fileName": "test2.jpeg",
    "filePath": "http://192.168.1.65:9006/directory/item/test2.jpeg?path=test&preview=1&key=default"
  },
  {
    "fileName": "test3.jpg",
    "filePath": "http://192.168.1.65:9006/directory/item/test3.jpg?path=test&preview=1&key=default"
  },
  {
    "fileName": "test4.jpeg",
    "filePath": "http://192.168.1.65:9006/directory/item/test4.jpeg?path=test&preview=1&key=default"
  },
  {
    "fileName": "test5.jpeg",
    "filePath": "http://192.168.1.65:9006/directory/item/test5.jpeg?path=test&preview=1&key=default"
  },
  {
    "fileName": "test6.jpeg",
    "filePath": "http://192.168.1.65:9006/directory/item/test6.jpeg?path=test&preview=1&key=default"
  },
  {
    "fileName": "test7.jpeg",
    "filePath": "http://192.168.1.65:9006/directory/item/test7.jpeg?path=test&preview=1&key=default"
  },
  {
    "fileName": "test8.jpg",
    "filePath": "http://192.168.1.65:9006/directory/item/test8.jpg?path=test&preview=1&key=default"
  },
  {
    "fileName": "test9.jpg",
    "filePath": "http://192.168.1.65:9006/directory/item/test9.jpg?path=test&preview=1&key=default"
  }
]

效果

列表展示

图片预览

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Ant Design of Vue 是一个基于 Vue.js 的 UI 组件库,它提供了丰富的组件和样式,可以帮助开发者快速构建美观、易用的 Web 应用程序。其中,Ant Design of Vue 表单封装是一个非常实用的功能,它可以帮助开发者快速构建表单,包括表单验证、表单布局、表单提交等功能,大大提高了开发效率。同时,Ant Design of Vue 表单封装还支持自定义表单组件,开发者可以根据自己的需求定制表单组件,满足不同的业务需求。总之,Ant Design of Vue 表单封装是一个非常实用的功能,可以帮助开发者快速构建高质量的 Web 应用程序。 ### 回答2: Ant Design of Vue是一个基于Vue.js的UI组件库,它提供了一系列优雅且易用的组件,包含有丰富的UI组件、样式和交互行为,可以帮助我们快速构建漂亮而且功能强大的Web应用。 其中,表单是Ant Design of Vue中最核心、最常用的组件之一,因为表单是我们在前端开发中最常用的交互方式。Ant Design of Vue中针对表单封装的功能也非常丰富,主要包括以下几个方面: 1. 表单控件:Ant Design of Vue提供了一系列的表单控件,包括输入框、选择器、日期选择器、开关、单选框、复选框等,这些表单控件都有丰富的属性和事件可以自由控制,可以满足我们在不同的场景下的需求。 2. 表单校验:Ant Design of Vue提供了非常强大的表单校验功能,可以对表单进行必填、数据格式、长度等多个方面的校验,还可以自定义校验规则,方便我们在项目中灵活运用。 3. 表单布局:Ant Design of Vue提供了多种表单布局,包括水平布局、垂直布局、行内布局等,可以根据不同的需求选择不同的布局方式,在表单的美观性、可读性等方面都有很好的表现。 4. 表单数据处理:Ant Design of Vue提供了非常便捷的表单数据处理方式,可以将表单中的数据进行组装、序列化、反序列化等操作,快捷方便。 总之,Ant Design of Vue提供的表单封装功能非常丰富、易用,在我们的前端开发中应用广泛,可以大大提高我们的开发效率、代码质量和用户体验。 ### 回答3: Ant Design of Vue 是一个企业级 UI 设计语言和 Vue.js 的实现版本,其中包括了许多常用的组件,如表格、表单、对话框等。 在 Ant Design of Vue 中,表单是一个非常常用和重要的组件,用于网站的交互和数据处理。Ant Design of Vue 中的表单组件可以通过简单的代码来实现各种表单元素的布局、样式、校验和提交等功能,同时具有良好的用户体验和可维护性。 Ant Design of Vue 的表单封装主要包括三个部分:表单组件、表单项组件和校验规则。 表单组件Ant Design of Vue 中的一个顶层组件,用于包装整个表单。通过定义 props 来配置表单的属性和事件,例如表单的布局方式、表单项组件的数据和样式绑定、表单的提交和重置等。 表单项组件是表单中的一个子组件,用于表示一个表单的输入项,如输入框、单选框、复选框和下拉框等。通过定义 props 和 v-model 来绑定表单项和表单数据,并设置相应的属性和事件来实现校验、关联、联动和交互等功能。 校验规则是 Ant Design of Vue 中用于校验表单项数据合法性的组件。通过定义 rules 属性来配置校验规则,例如数据格式、数据类型、数据范围和数据比较等。当表单提交或失焦时,校验规则会自动进行校验,并在校验不通过时提示相应的错误信息。 总体来说,Ant Design of Vue 中的表单封装具有很高的可用性和可扩展性,能够满足各种不同的业务需求,并且对于前端开发人员来说也十分友好和方便。如果您需要构建一个高品质的企业级表单,那么 Ant Design of Vue 的表单封装一定是您的不二之选。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花姐夫Jun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值