使用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) {
// 邏輯操作
},
});
}
DirectiveBindingel的類型h將組件代碼轉(zhuǎn)成 vnoderender將 vnode 渲染成 html
下面開(kāi)始編寫相關(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-07
vue項(xiàng)目設(shè)置scrollTop不起作用(總結(jié))
這篇文章主要介紹了vue項(xiàng)目設(shè)置scrollTop不起作用(總結(jié)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
Element-Plus之el-col與el-row快速布局
el-col是el-row的子元素,下面這篇文章主要給大家介紹了關(guān)于Element-Plus之el-col與el-row快速布局的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09
Vue實(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-02
vue實(shí)現(xiàn)文字轉(zhuǎn)語(yǔ)音功能詳解
這篇文章主要介紹了vue實(shí)現(xiàn)文字轉(zhuǎn)語(yǔ)音功能詳解的相關(guān)資料,需要的朋友可以參考下2022-09-09

