使用vue3指令封裝一個(gè)圖片預(yù)覽功能
最近公司搭建了一個(gè)新的 vue3 項(xiàng)目,因?yàn)轫?xiàng)目中有很多模塊用到了圖片預(yù)覽功能,項(xiàng)目的 ui 框架用的是element-plus,框架自帶 el-image 組件里面帶了圖片預(yù)覽功能,但是當(dāng)時(shí)我不想用這個(gè)組件,所以就借鑒了它里面預(yù)覽圖片組件的代碼。
復(fù)習(xí)vue3指令的寫法
簡(jiǎn)單的例子
<div v-color="red"> 我是紅色的文字</div>
app.directive('color', (el, binding) => { // 這會(huì)在 `mounted` 和 `updated` 時(shí)都調(diào)用 el.style.color = binding.value })
這時(shí)候 div 里面的文字都變成紅色, v-color="yellow" 就變成了黃色
相關(guān)參數(shù)介紹
el
:指令綁定到的元素。這可以用于直接操作 DOM。binding
:一個(gè)對(duì)象,包含以下屬性。value
:傳遞給指令的值。例如在v-my-directive="1 + 1"
中,值是2
。oldValue
:之前的值,僅在beforeUpdate
和updated
中可用。無(wú)論值是否更改,它都可用。arg
:傳遞給指令的參數(shù) (如果有的話)。例如在v-my-directive:foo
中,參數(shù)是"foo"
。modifiers
:一個(gè)包含修飾符的對(duì)象 (如果有的話)。例如在v-my-directive.foo.bar
中,修飾符對(duì)象是{ foo: true, bar: true }
。instance
:使用該指令的組件實(shí)例。dir
:指令的定義對(duì)象。vnode
:代表綁定元素的底層 VNode。prevNode
:代表之前的渲染中指令所綁定元素的 VNode。僅在beforeUpdate
和updated
鉤子中可用。
新建 previewImageDirective.ts 文件
導(dǎo)入相關(guān)函數(shù)及類型,編寫基本的指令代碼
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
將組件代碼轉(zhuǎn)成 vnoderender
將 vnode 渲染成 html
下面開始編寫相關(guān)指令代碼
首先我們需要?jiǎng)?chuàng)建一個(gè) div 用來(lái)包裹我們的預(yù)覽組件,我們來(lái)控制這個(gè) div 的顯示隱藏來(lái)實(shí)現(xiàn)預(yù)覽組件的彈出和隱藏。
為什么這幾個(gè)變量為啥要定義成全局的,如果寫在指令內(nèi)部 v-previewImage="" 多次 就出現(xiàn)多個(gè)變量,和多個(gè)組件,造成了資源浪費(fèi),然后ElImageViewer組件一個(gè)頁(yè)面要寫多次還會(huì)出現(xiàn)一個(gè)錯(cuò)誤
我給 element 提了issues,現(xiàn)在已經(jīng)修復(fù),但還是推薦我這種寫法
const previewBox = document.createElement('div'); // 創(chuàng)建節(jié)點(diǎn) previewBox.classList.add('preview-box'); // 給 div 增加類名 let vnode; // 存放 vnode 的變量
編寫指令內(nèi)部代碼
第一步給圖片綁定點(diǎn)擊事件并給圖片添加樣式,當(dāng)鼠標(biāo)滑過(guò)添加小手的樣式
export default function (app) { app.directive('previewImage', { mounted(el: HTMLElement, binding: DirectiveBinding) { el.addEventListener('click', () => { el.style.cursor = 'pointer'; }) }, }); }
第二步 使用 h 函數(shù) 渲染組件 將組件代碼轉(zhuǎn)成 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, // 允許點(diǎn)擊遮罩層關(guān)閉 }); }, }); }
第三步 使用 render 函數(shù)將 vnode 渲染到我們創(chuàng)建的div 里面,并且將我們創(chuàng)建的 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, // 允許點(diǎn)擊遮罩層關(guān)閉 }); render(vnode, previewBox); // 將 vnode 渲染成 html document.body.appendChild(previewBox); // 將 html 插入到 body 標(biāo)簽里面 }, }); }
到現(xiàn)在為止我們點(diǎn)擊圖片組件已經(jīng)可以正常的顯示了
第四步當(dāng)點(diǎn)擊遮罩層關(guān)閉的時(shí)候?qū)⑽覀儎?chuàng)建的 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, // 允許點(diǎn)擊遮罩層關(guān)閉 onClose: () => { el.removeEventListener('click', () => {}); // 移除 document.body.removeChild(previewBox); }, }); render(vnode, previewBox); // 將 vnode 渲染成 html document.body.appendChild(previewBox); // 將 html 插入到 body 標(biāo)簽里面 }, }); }
將文件導(dǎo)入到 main.ts中
將文件導(dǎo)入 main.ts中然后調(diào)用我們導(dǎo)入的方法傳入 app 就可以在頁(yè)面中使用了
import imageDirective from 'xxxx/previewImageDirective'; const app = createApp(App); imageDirective(app)
ok 上面就是完整代碼,這樣一個(gè)圖片預(yù)覽指令就完成了
以上就是使用vue3指令封裝一個(gè)圖片預(yù)覽功能的詳細(xì)內(nèi)容,更多關(guān)于vue3圖片預(yù)覽的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
VSCode前端Vue項(xiàng)目引入Element-ui組件三步簡(jiǎn)單操作方法
elementui相當(dāng)于一個(gè)庫(kù),封裝好的內(nèi)容,我們引入到vue項(xiàng)目中,就可用庫(kù)中的內(nèi)容,這篇文章主要給大家介紹了關(guān)于VSCode前端Vue項(xiàng)目引入Element-ui組件的三步簡(jiǎn)單操作方法,需要的朋友可以參考下2024-07-07vue項(xiàng)目設(shè)置scrollTop不起作用(總結(jié))
這篇文章主要介紹了vue項(xiàng)目設(shè)置scrollTop不起作用(總結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12Element-Plus之el-col與el-row快速布局
el-col是el-row的子元素,下面這篇文章主要給大家介紹了關(guān)于Element-Plus之el-col與el-row快速布局的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09Vue實(shí)現(xiàn)登錄保存token并校驗(yàn)實(shí)現(xiàn)保存登錄狀態(tài)的操作代碼
這篇文章主要介紹了Vue實(shí)現(xiàn)登錄保存token并校驗(yàn)實(shí)現(xiàn)保存登錄狀態(tài),本文通過(guò)示例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧2024-02-02vue實(shí)現(xiàn)文字轉(zhuǎn)語(yǔ)音功能詳解
這篇文章主要介紹了vue實(shí)現(xiàn)文字轉(zhuǎn)語(yǔ)音功能詳解的相關(guān)資料,需要的朋友可以參考下2022-09-09