基于elementUI创建图片预览函数

100 阅读2分钟

背景

element-ui没有直接用js调用图片的组件,自己写一下

写图片预览组件前,我们要了解两个vue方法:

1:h()

它是render函数的辅助函数,用来创建虚拟DOM。

它接受三个参数,第一个是需要创建的组建或者普通标签;第二个是传递给组建的props或者标签属性;第三个参数是标签内加上内容,第一个参数为组件是无效。

2:render()

render函数就是将h()方法生成的虚拟DOM转换成真实DOM,再渲染到指定DOM下。

它接受两个参数,第一个是h()生出的虚拟DOM;第二个是渲染到哪个DOM下。

// 创建标签
const vNode = h('div', {
    class: 'demo'
}, '内容')
render(vNode, document.body)
// 相当于在body标签下创建
// <div class="demo">内容</div>

// 创建组件
const vNode = h(imagePreview, {
    url,
    cancelHandler
})
render(vNode, document.body)
// 相当于在body标签下创建
// <imagePreview :url="url" :cancelHandler="cancelHandler" />

了解了这两个方法后我们就可以分三步走来写图片预览组件了。

实现

第一步

我们建一个图片预览组件image.vue,主要就两点,一个是接收外部传入的图片url,另一个是关闭图片预览事的回调事件。

<template>
    <div class="wrap">
        <img :src="url" alt="">
        <div class="close" @click="handleCancel">x</div>
    </div>
</template>

<script setup>
import { onMounted, ref, render } from 'vue';

const props = defineProps({
    // 接收传入的图片url
    url: {
        type: String,
        default: ''
    },
    // 关闭回调事件
    cancelHandler: {
        type: Function
    }
})

// 关闭事件
const handleCancel = () => {
    // 调用回调事件
    props.cancelHandler()
    // 清空dom
    render(null, document.body)
}
</script>

<style lang="less" scoped>
.wrap {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 100;
    background-color: rgba(0, 0, 0, .2);
    img {
        max-width: 100%;
        max-height: 100%;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
    }
    .close {
        position: absolute;
        right: 20px;
        top: 20px;
        width: 50px;
        height: 50px;
        line-height: 50px;
        text-align: center;
        background-color: #fff;
        border-radius: 50%;
        cursor: pointer;
    }
}
</style>

第二步

创建imgPreview.js来生成图片预览组件dom,以及将创建方法暴露出去。

import { h, render } from 'vue'
import image from './imagePreview.vue'

export const imagePreview = (url) => {
    // 使用promise,在关闭预览后,.then里可以做后面的操作
    return new Promise((reslove, reject) => {
        // 关闭后reslove()
        const cancelHandler = () => {
            reslove()
        }

        // 创建图片预览组件虚拟dom
        const vNode = h(image, {
            url,
            cancelHandler
        })

        // 将图片预览组件渲染到body标签下
        render(vNode, document.body)
    })
}

第三步

就是调用imagePreview方法来使用图片预览组件了

<template>
    <div class="demo">
        <button @click="handlePreview">预览图片</button>
    </div>
</template>

<script setup>
import { imagePreview } from '@/components/imagePreview.js'
const handlePreview = () => {
    imagePreview('https://img2.baidu.com/it/u=2719958522,3840000478&fm=253&fmt=auto&app=138&f=JPEG?w=380&h=380').then(() => {
        console.log('关闭图片')
    })
}
</script>

<style lang="less" scoped>

</style>