當前位置: 妍妍網 > 碼農

使用 Vue3 指令封裝一個後台管理系統圖片預覽功能

2024-02-21碼農

今天給大家推薦一個Vue3的文章

前言

最近公司搭建了一個新的 vue3 計畫,因為計畫中有很多模組用到了圖片預覽功能,計畫的 ui 框架用的是element-plus,框架內建 el-image 元件裏面帶了圖片預覽功能,但是當時我不想用這個元件,所以就借鑒了它裏面預覽圖片元件的程式碼。

復習vue3指令的寫法

官方指令文件 [1]

簡單的例子

<divv-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';
    exportdefaultfunction (app{
     app.directive('previewImage', {
    mounted(el: HTMLElement, binding: DirectiveBinding) {
    // 邏輯操作
    },
     });
    }

  • DirectiveBinding el的型別

  • h 將元件程式碼轉成 vnode

  • render 將 vnode 渲染成 html

  • 下面開始編寫相關指令程式碼

    首先我們需要建立一個 div 用來包裹我們的預覽元件,我們來控制這個 div 的顯示隱藏來實作預覽元件的彈出和隱藏。

    為什麽這幾個變量為啥要定義成全域的,如果寫在指令內部 v-previewImage="" 多次 就出現多個變量,和多個元件,造成了資源浪費,然後ElImageViewer元件一個頁面要寫多次還會出現一個錯誤

    我給 element 提了issues,現在已經修復,但還是推薦我這種寫法

    const previewBox = document.createElement('div'); // 建立節點
    previewBox. classList.add('preview-box'); // 給 div 增加類名
    let vnode; // 存放 vnode 的變量

    編寫指令內部程式碼

  • 第一步給圖片繫結點選事件並給圖片添加樣式,當滑鼠滑過添加小手的樣式

  • exportdefaultfunction (app{
     app.directive('previewImage', {
    mounted(el: HTMLElement, binding: DirectiveBinding) {
    el.addEventListener('click', () => {
    el. style.cursor = 'pointer';
    })
    },
     });
    }

  • 第二步 使用 h 函式 渲染元件 將元件程式碼轉成 vnode

  • exportdefaultfunction (app{
     app.directive('previewImage', {
    mounted(el: HTMLElement, binding: DirectiveBinding) {
    el.addEventListener('click', () => {
    el. style.cursor = 'pointer';
    })
    vnode = h(ElImageViewer, {
    urlList: [binding.value], // 圖片地址
    hideOnClickModaltrue// 允許點選遮罩層關閉
    });
    },
     });
    }

  • 第三步 使用 render 函式將 vnode 渲染到我們建立的div 裏面,並且將我們建立的 div 插入到 body 裏面

  • exportdefaultfunction (app{
     app.directive('previewImage', {
    mounted(el: HTMLElement, binding: DirectiveBinding) {
    el.addEventListener('click', () => {
    el. style.cursor = 'pointer';
    })
    vnode = h(ElImageViewer, {
    urlList: [binding.value], // 圖片地址
    hideOnClickModaltrue// 允許點選遮罩層關閉
    });
    render(vnode, previewBox); // 將 vnode 渲染成 html
    document.body.appendChild(previewBox); // 將 html 插入到 body 標簽裏面
    },
     });
    }

    到現在為止我們點選圖片元件已經可以正常的顯示了

    image.png
  • 第四步當點選遮罩層關閉的時候將我們建立的 div 移除掉就 ok 了

  • exportdefaultfunction (app{
     app.directive('previewImage', {
    mounted(el: HTMLElement, binding: DirectiveBinding) {
    el.addEventListener('click', () => {
    el. style.cursor = 'pointer';
    })
    vnode = h(ElImageViewer, {
    urlList: [binding.value], // 圖片地址
    hideOnClickModaltrue// 允許點選遮罩層關閉
    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 上面就是完整程式碼,這樣一個圖片預覽指令就完成了

    作者:前端Ah
    連結:https://juejin.cn/post/7324653675456364596
    來源:稀土金塊

    結語