title: Removing event listener in beforeDestroy lifecycle method does not work if element was removed by v-if in a parent component
body: <p>Basically I am using a datepicker library that does not emit focus or blur events, so I need to add them manually, but I am having trouble removing the event listeners due to an upstream <code>v-if</code>.</p>
  
  <p>I did it like this:</p>
  
  <pre><code>&lt;datepicker :id="datePickerId"&gt;
  </code></pre>
  
  <p>...</p>
  
  <pre><code>computed: {
      datePickerId() { return `date-picker-${this.name}`; },
  },
  
  mounted() {
      document.getElementById(this.datePickerId).addEventListener('focus', this.handleFocus);
      document.getElementById(this.datePickerId).addEventListener('blur', this.handleBlur);
  },
  
  beforeDestroy() {
      document.getElementById(this.datePickerId).removeEventListener('focus', this.handleFocus);
      document.getElementById(this.datePickerId).removeEventListener('blur', this.handleBlur);
  },
  </code></pre>
  
  <p>This works fine until my component is conditionally-rendered via <code>v-if</code>, such as:</p>
  
  <pre><code>&lt;my-datepicker v-if="isDisplayed"&gt;
  </code></pre>
  
  <p>I've researched it, and the problem appears to be because the input element is removed from the DOM due to <code>v-if</code> but the Vue instance still exists, so the <code>beforeDestroy</code> lifecycle method is called after the element is already gone.</p>
  
  <p>Short of just omitting the cleanup step and relying on modern browser garbage collection, is there any way to prevent memory leaks?</p>
  
  <p>I am extremely interested to learn more about how to gain more control over what is happening around the time <code>v-if</code> goes falsy. There isn't many articles/issues/tickets about this "inopportune moment in time", so if anyone has any related input, please feel free to add it.</p>
  
  <p>Is there any other way to tap into the 3rd party library's input's focus/blur events?</p>
  
  <blockquote>
    <p>[Vue warn]: Error in beforeDestroy hook: "TypeError: Cannot read property 'removeEventListener' of null"</p>
  </blockquote>