Build a Vue3 Custom Directive for Image Preview in an Admin Dashboard

This article walks through creating a Vue3 custom directive that leverages Element‑Plus's ElImageViewer to provide image preview functionality in a backend admin system, covering directive registration, event binding, vnode creation, rendering, and cleanup with full code examples.

IoT Full-Stack Technology
IoT Full-Stack Technology
IoT Full-Stack Technology
Build a Vue3 Custom Directive for Image Preview in an Admin Dashboard

Review Vue3 directive syntax

The official Vue3 custom directive documentation is referenced, and a simple <div v-color="red">我是红色的文字</div> example demonstrates how a directive can modify the bound element's style.

Create previewImageDirective.ts

Import required types and components, then register a previewImage directive:

import { DirectiveBinding, h, render } from 'vue'
import { ElImageViewer } from 'element-plus'

export default function (app) {
  app.directive('previewImage', {
    mounted(el: HTMLElement, binding: DirectiveBinding) {
      // logic will be added later
    }
  })
}

Explain directive parameters

el

: the element the directive is bound to, used for direct DOM manipulation. binding: an object containing value, oldValue, arg, modifiers, instance, and vnode information. value: the value passed to the directive, e.g., v-my-directive="1 + 1" yields 2. oldValue: previous value, available in beforeUpdate and updated hooks. arg: optional argument, e.g., v-my-directive:foo gives "foo". modifiers: object of modifiers, e.g., { foo: true, bar: true } for v-my-directive.foo.bar. instance: the component instance using the directive. vnode: the underlying VNode of the bound element. prevNode: previous render's VNode, usable in beforeUpdate and updated.

Implement the directive logic

Step 1 – bind a click event and change the cursor style:

export default function (app) {
  app.directive('previewImage', {
    mounted(el: HTMLElement, binding: DirectiveBinding) {
      el.addEventListener('click', () => {
        el.style.cursor = 'pointer'
      })
    }
  })
}

Step 2 – use the h function to create a vnode for ElImageViewer with the image URL and hideOnClickModal option:

vnode = h(ElImageViewer, {
  urlList: [binding.value], // image address
  hideOnClickModal: true // allow closing by clicking the overlay
})

Step 3 – render the vnode into a dynamically created div and append it to document.body:

const previewBox = document.createElement('div')
previewBox.classList.add('preview-box')
render(vnode, previewBox)
document.body.appendChild(previewBox)

Step 4 – when the overlay is clicked, remove the created div and clean up listeners:

onClose: () => {
  el.removeEventListener('click', () => {})
  document.body.removeChild(previewBox)
}

Import the directive in main.ts

Finally, import the directive file and invoke it with the Vue app instance:

import imageDirective from 'xxxx/previewImageDirective'
const app = createApp(App)
imageDirective(app)

After these steps, any element with v-previewImage="imageUrl" will display a clickable preview that opens the Element‑Plus image viewer and closes cleanly.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

frontendVue3custom directiveelement-plusimage preview
IoT Full-Stack Technology
Written by

IoT Full-Stack Technology

Dedicated to sharing IoT cloud services, embedded systems, and mobile client technology, with no spam ads.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.