使用vue3指令封装一个图片预览功能
作者:前端Ah
这篇文章主要为大家详细介绍了如何使用 vue3 指令封装一个后台管理系统图片预览功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
最近公司搭建了一个新的 vue3 项目,因为项目中有很多模块用到了图片预览功能,项目的 ui 框架用的是element-plus,框架自带 el-image 组件里面带了图片预览功能,但是当时我不想用这个组件,所以就借鉴了它里面预览图片组件的代码。
复习vue3指令的写法
简单的例子
<div v-color="red"> 我是红色的文字</div>
app.directive('color', (el, binding) => { // 这会在 `mounted` 和 `updated` 时都调用 el.style.color = binding.value })
这时候 div 里面的文字都变成红色, v-color="yellow" 就变成了黄色
相关参数介绍
el
:指令绑定到的元素。这可以用于直接操作 DOM。binding
:一个对象,包含以下属性。value
:传递给指令的值。例如在v-my-directive="1 + 1"
中,值是2
。oldValue
:之前的值,仅在beforeUpdate
和updated
中可用。无论值是否更改,它都可用。arg
:传递给指令的参数 (如果有的话)。例如在v-my-directive:foo
中,参数是"foo"
。modifiers
:一个包含修饰符的对象 (如果有的话)。例如在v-my-directive.foo.bar
中,修饰符对象是{ foo: true, bar: true }
。instance
:使用该指令的组件实例。dir
:指令的定义对象。vnode
:代表绑定元素的底层 VNode。prevNode
:代表之前的渲染中指令所绑定元素的 VNode。仅在beforeUpdate
和updated
钩子中可用。
新建 previewImageDirective.ts 文件
导入相关函数及类型,编写基本的指令代码
import { DirectiveBinding, h, render } from 'vue'; import { ElImageViewer } from 'element-plus'; export default function (app) { app.directive('previewImage', { mounted(el: HTMLElement, binding: DirectiveBinding) { // 逻辑操作 }, }); }
DirectiveBinding
el的类型h
将组件代码转成 vnoderender
将 vnode 渲染成 html
下面开始编写相关指令代码
首先我们需要创建一个 div 用来包裹我们的预览组件,我们来控制这个 div 的显示隐藏来实现预览组件的弹出和隐藏。
为什么这几个变量为啥要定义成全局的,如果写在指令内部 v-previewImage="" 多次 就出现多个变量,和多个组件,造成了资源浪费,然后ElImageViewer组件一个页面要写多次还会出现一个错误
我给 element 提了issues,现在已经修复,但还是推荐我这种写法
const previewBox = document.createElement('div'); // 创建节点 previewBox.classList.add('preview-box'); // 给 div 增加类名 let vnode; // 存放 vnode 的变量
编写指令内部代码
第一步给图片绑定点击事件并给图片添加样式,当鼠标滑过添加小手的样式
export default function (app) { app.directive('previewImage', { mounted(el: HTMLElement, binding: DirectiveBinding) { el.addEventListener('click', () => { el.style.cursor = 'pointer'; }) }, }); }
第二步 使用 h 函数 渲染组件 将组件代码转成 vnode
export default function (app) { app.directive('previewImage', { mounted(el: HTMLElement, binding: DirectiveBinding) { el.addEventListener('click', () => { el.style.cursor = 'pointer'; }) vnode = h(ElImageViewer, { urlList: [binding.value], // 图片地址 hideOnClickModal: true, // 允许点击遮罩层关闭 }); }, }); }
第三步 使用 render 函数将 vnode 渲染到我们创建的div 里面,并且将我们创建的 div 插入到 body 里面
export default function (app) { app.directive('previewImage', { mounted(el: HTMLElement, binding: DirectiveBinding) { el.addEventListener('click', () => { el.style.cursor = 'pointer'; }) vnode = h(ElImageViewer, { urlList: [binding.value], // 图片地址 hideOnClickModal: true, // 允许点击遮罩层关闭 }); render(vnode, previewBox); // 将 vnode 渲染成 html document.body.appendChild(previewBox); // 将 html 插入到 body 标签里面 }, }); }
到现在为止我们点击图片组件已经可以正常的显示了
第四步当点击遮罩层关闭的时候将我们创建的 div 移除掉就 ok 了
export default function (app) { app.directive('previewImage', { mounted(el: HTMLElement, binding: DirectiveBinding) { el.addEventListener('click', () => { el.style.cursor = 'pointer'; }) vnode = h(ElImageViewer, { urlList: [binding.value], // 图片地址 hideOnClickModal: true, // 允许点击遮罩层关闭 onClose: () => { el.removeEventListener('click', () => {}); // 移除 document.body.removeChild(previewBox); }, }); render(vnode, previewBox); // 将 vnode 渲染成 html document.body.appendChild(previewBox); // 将 html 插入到 body 标签里面 }, }); }
将文件导入到 main.ts中
将文件导入 main.ts中然后调用我们导入的方法传入 app 就可以在页面中使用了
import imageDirective from 'xxxx/previewImageDirective'; const app = createApp(App); imageDirective(app)
ok 上面就是完整代码,这样一个图片预览指令就完成了
以上就是使用vue3指令封装一个图片预览功能的详细内容,更多关于vue3图片预览的资料请关注脚本之家其它相关文章!