proper way to delete an event listener in vue 3

I have a function that listens for viewport dimensions when the project is first mounted and also after each resize event.

However, I am unsure of the correct way to remove this listener.

const { createApp, onMounted, ref } = Vue;
const app = createApp({
  setup() {
    const dim = ref({})
    
    onMounted(() => {
      dim.value = getDimensions()
      // adding the event listener...
      window.addEventListener('resize', debounce(() => {
        // ...but how to properly remove it later?
        console.log('resize')
        dim.value = getDimensions()
      }, 250))
    })
    
    function getDimensions () {
      return {
        w: window.innerWidth,
        h: window.innerHeight
      }
    }
    
    // generic debounce function
    function debounce (func, wait) {
    let timeout
    return function executedFunction (...args) {
      const later = () => {
      timeout = null
          func(...args)
        }
        clearTimeout(timeout)
        timeout = setTimeout(later, wait)
      }
    }

    return {
      dim
    }
  }
});
app.mount("#app");
.navbar {
  position: fixed;
  width: 100%;
  height: 50px;
  top: 0;
  left: 0;
  background-color: #555;
  text-align: center;
}
p {
    color: #fff;
}
<script src="https://unpkg.com/vue@next"></script>

<div id="app">
  <div class="navbar">
    <p>
      <span>width: {{ dim.w + ' ' }}</span>
      <span>| height: {{ dim.h }}</span>
    </p>
  </div>
</div>

Any tips on removing the event listener correctly?

The technology I'm using is Vue 3 with Composition API.

Answer №1

Why not use the unmounted life cycle hook instead? Check out the documentation for more information

window.removeEventListener("resize", debounce);

If you're working with Vue 3 Composition API, consider using the onUnmounted hook (refer to the docs for details)

Answer №2

If you're looking to simplify adding event listeners in Vue, give VueUse's useEventListener a try. It even handles removing the listener when the component is unmounted.

Here's an example straight from the documentation:

import { useEventListener } from '@vueuse/core'

const element = ref<HTMLDivElement>()
useEventListener(element, 'keydown', (e) => {
  console.log(e.key)
})

Answer №3

My preferred approach is to define the event method outside of the mounted hook

onResize() {
    debounce(() => {
        // ...however, how do I properly remove the event listener?
        console.log('resize')
        dim.value = getDimensions()
      }, 250))
    })
}

Then, within the mounted hook, you can implement it like this

onMounted(() => {
  dim.value = getDimensions()
  // adding the event listener...
  window.addEventListener('resize', this.onResize)
})

Finally, in the beforeUnmount hook

beforeUnmount(() => {
  window.removeEventListener('resize', this.onResize)
})

Answer №4

When using vue 3 script setup, the implementation is as follows:

<script setup>
import {onMounted, onUnmounted} from "vue";

function yourFunction(event) {
    // Add your functionality here
}

onMounted(() => {
    window.addEventListener('click', yourFunction)
})

onUnmounted(() => {
    window.removeEventListener('click', yourFunction);
})
</script>

If you have found a way to remove event listeners from anonymous functions, please share it with me.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The second parameter of the Ajax request is not defined

Having an issue with my Ajax request in Vue.js where the second parameter is logging as undefined in the console. I've been trying to fix this problem but haven't found a solution yet. This is the code snippet for $.ajax(): //$.ajax() to add ag ...

When using vue-router push, the first page should not be concealed even if the data array is extensive

After navigating from Home.vue to History.vue using this.$router.push("/history/" + fileid);, a socket.io request is triggered in the created or mounted lifecycle hook which fetches a large amount of data. The rendering process, especially with v-for, take ...

Tips for avoiding the automatic transition to the next slide in SwiperJS

How can I prevent the next button click in swiper based on my custom logic? I am using the swiperjs library within a Vue project and I need to stop users from swiping or clicking the next button to move to the next slide depending on certain conditions de ...

How to access a file stored within a proxy object using Vue.js

I am currently working on sending a file from a vue-page to the server. To achieve this, I have implemented the following: FileFrom component: <template> <div class="FileForm" v-bind:name="name"> <label clas ...

Tips for extracting a computed property value and storing it in an array variable

In my project, I have implemented a computed property function named Total. This function is responsible for calculating the total value of name + value pairs from an array called prices. It is utilized in a quotation form where the running total is displa ...

The build process encountered an error due to the absence of ESLint configuration after the import

Having recently worked on a Vue project created using Vue CLI, I found that eslint was also included in the project. Although I haven't utilized eslint much up to this point, I understand that it is beneficial for catching stylistic errors, semantic e ...

Vuetify does not support Tailwind CSS styles

Initially, I integrated Tailwind CSS into my project. However, during the development process, I decided to give Vuetify a try. After adding Vuetify along with vuetify-loader, I encountered an issue where Vuetify functionality was working fine but the styl ...

Implementing SweetAlert2 in Vue.js to create a modal prompt for confirmation prior to deleting an item

I'm encountering an issue with sweetalert2 while using Laravel Vue for my app development. My goal is to have a confirmation modal pop-up when deleting a row from the database. However, whenever I click "Yes", the item is successfully removed. But if ...

Incorporate a Vue directive based on a certain condition

Can a directive be set based on a condition? I have a directive called "sticky" that makes elements stick to the screen. I am currently using it in a social share component. <tempalte> <div class="social-share" v-sticky> .... ...

Illustrative demonstration of Vue with TypeScript

I am currently working on developing a HelloWorld application using Vue.js and TypeScript. index.html <script data-main="app.js" src="node_modules/requirejs/require.js"></script> <div id="app">{{text}}</div> app.ts import Vue f ...

What is the best way to anticipate the vue.js created hook?

I have a vue.js application where I am facing an issue with awaiting a call to the Prismic API. The call is initiated from the created hook, but I am unsure of how to make Vue await the hook itself. Here is an example of the code: ... async created() { ...

Is it recommended to utilize CDN in Vue.js for optimal performance?

Currently facing a version compatibility issue between leaflet and leaflet-draw in my vuejs project. In light of this, I am seeking alternative solutions for map function editing such as adding polylines, copy and paste functions, and more. While I did com ...

Is there a Nuxt/Vue glitch causing the server to be called multiple times on a single route or page?

Why is Nuxt making multiple server calls on a single route/page? I tested the example from their express-template: import express from 'express' import { Nuxt, Builder } from 'nuxt' import api from './api' const app = expr ...

Navigating using Vue Router: Automatically redirect to the homepage if the user is trying to reload a subpage

How can I redirect to the root of my Vue application when a user reloads a subpage in order to perform some initialization work? Below is my current routing setup: const routes: RouteRecordRaw[] = [ { path: '/', component: HeaderLayout ...

Troubleshooting Issue: Difficulty with color--text not displaying in Vue 3/Vuetify 3 Integration

Today, I attempted to set up Vuetify with Vue3 for the first time. Most things seem to be working fine: components are being imported correctly, and classes like "text-center" are functioning as expected. However, I have noticed that props such as "dark" ...

What is causing Vue to not update a list when using props?

When my App loads, I make an API call in the mounted() method to retrieve a JSON with a list of items. After that, I update the prop set in my target component Homepage: Homepage.pages = resJSON.data.pages; Take a look at the App code below: <template& ...

Enhancing UI design with Vue.js

I'm attempting to customize elements using data from a JSON file in Vue.js: <div v-for="(item, index) in json._items" class="help-inner-callout" v-html="item.text" style="top:item.top; left: item.left;">&l ...

"Enhance your development experience with the TypeScript definitions for the Vue 2 plugin

Currently, I am utilizing VSCode alongside TypeScript classes for developing Vue 2 components. You can check out more information at: vuejs/vue-class-component. Within my present project, I make use of plugins like vue-i18n for handling translations of la ...

What is the process for switching the default font in Vuetify from Roboto to a different typeface for all elements?

Is there a way to update the font for all elements in Vuetify from Roboto to another option? I am currently using Vuetify, which comes with the default Roboto font. However, I would like to switch it to a different font. Modifying the font in the variable ...

Encountering a hindrance with NPM proxy while attempting to globally install Vue CLI

I have encountered an issue while trying to install Vue Cli globally. The installation process is not completing and I am receiving errors related to proxy settings. I tried to manually add values to the .npmrc file as shown below, but it did not resolve t ...