Vue 3 Click Away Directive
vue3-click-away is a Vue 3.x compatible directive designed to detect click events that occur outside of a specified element. It provides a simple mechanism for components to react when a user clicks anywhere on the document except on the element itself or its children. Currently at version 1.2.4, the package sees irregular but active maintenance, primarily addressing critical fixes such as recent server-side rendering (SSR) compatibility issues. Key differentiators include its explicit support for Vue 3's plugin system, direct directive registration, and a mixin option, offering flexibility in integration depending on the project's setup and preference. It ships with TypeScript types, facilitating its use in TypeScript-first Vue projects. Its primary goal is to abstract away the complexity of managing global click listeners for 'click away' scenarios.
Common errors
-
Failed to resolve directive: click-away
cause The `v-click-away` directive has not been registered globally or locally in the component.fixGlobally register the directive using `app.use(VueClickAway)` where `VueClickAway` is the default import. Alternatively, locally register it within your component's `directives` option: `import { directive } from 'vue3-click-away'; directives: { ClickAway: directive }`. -
TypeError: Cannot read properties of undefined (reading 'use')
cause Attempting to use `VueClickAway` as a plugin on a non-Vue app instance, or `VueClickAway` was incorrectly imported (e.g., using named import for the plugin).fixEnsure `VueClickAway` is imported as the default export (`import VueClickAway from 'vue3-click-away'`) and that `app.use()` is called on a valid Vue 3 application instance created with `createApp()`. -
Error: Hydration completed but contains mismatches.
cause This usually indicates an issue where the server-rendered HTML differs from the client-rendered output, often related to directives or dynamic content, particularly in SSR environments with older versions of the package.fixUpdate `vue3-click-away` to the latest version (1.2.4+). If the problem persists, consider wrapping the component using `v-click-away` in a `<ClientOnly>` component (if your SSR framework supports it) to ensure the directive is only active on the client-side.
Warnings
- breaking The package transitioned from being solely a directive to also exporting a plugin in v1.1.0. While the directive export remains, the primary recommended usage shifted towards the plugin approach via `app.use()`. Direct registrations of the directive might need adjustments or ensure correct named import.
- gotcha Early versions (prior to v1.2.3) had known issues with Server-Side Rendering (SSR) environments, potentially leading to hydration mismatches or errors. These were addressed in subsequent patches, but complex SSR setups might still require careful testing.
- gotcha When using the directive, the `v-click-away` handler function receives the native `MouseEvent` object as its argument. If your handler expects different parameters or uses an incorrect signature, it might lead to unexpected behavior.
Install
-
npm install vue3-click-away -
yarn add vue3-click-away -
pnpm add vue3-click-away
Imports
- VueClickAway
import { VueClickAway } from 'vue3-click-away'import VueClickAway from 'vue3-click-away'
- directive
import directive from 'vue3-click-away'
import { directive } from 'vue3-click-away' - mixin
import mixin from 'vue3-click-away'
import { mixin } from 'vue3-click-away'
Quickstart
import { createApp } from 'vue';
import VueClickAway from 'vue3-click-away';
const App = {
template: `
<div style="padding: 20px; border: 1px solid #ccc;" v-click-away="onClickAway">
Click inside me! ({{ clickCount }} clicks)
<p>This box detects clicks outside itself.</p>
</div>
<button @click="resetCount">Reset Counter</button>
<p>Click anywhere else on the page.</p>
`,
data() {
return { clickCount: 0 };
},
methods: {
onClickAway(event) {
this.clickCount++;
console.log('Clicked away!', event);
},
resetCount() {
this.clickCount = 0;
}
}
};
const app = createApp(App);
app.use(VueClickAway); // Register the directive globally
app.mount('#app');
// To run this in a real HTML file, you would need a div with id="app":
// <div id="app"></div>