vue.jsinputhookrefs

Cannot read properties of undefined (reading '$refs') vue js


Getting the Error Cannot read properties of undefined (reading '$refs') though I'm having a reference in the template. Does it mean I must use Vue mounted hook ?

<div class="input-wrapper">
   <input type="text" id="phone" placeholder="(555) 555-5555" ref="input"/>
</div>
                            
<script>                   
  this.$refs.input.addEventListener('input', function () {
        // some code
 });
</script>

Solution

  • Inside root of <script> of a Vue component, in both Vue 2 and Vue 3, this is undefined:

    <script>
      console.log(this) // undefined
    </script>
    

    See it here.


    Vue template refs can only be accessed inside any hook or method happening after the component has been mounted and before it is unmounted.

    Which means the earliest you can reference this.$refs is inside mounted. And the latest is in beforeUnmount. And you can also access them in any hook or method happening between those two moments.


    Considering you're attempting to add an event listener to a HTMLInputElement, I'd recommend using the v-on directive, which automatically adds the event listener on mount and removes it on unmount.

    In your case:

    <template>
      <div class="input-wrapper">
        <input 
          type="text"
          id="phone"
          placeholder="(555) 555-5555"
          @input="myFn" />
      </div>
    </template>
                                
    <script>
    export default {
      methods: {
        myFn(event) {
          console.log(event)
        }
      }
    }
    </script>
    

    As a side note, you should know that a regular function's this doesn't have access to the component context, unless it's an arrow function:

    export default {
      mounted() {
        this.$refs.input.addEventListener('input', function() {
          /*
           * Here `this` is the context of the current function, you can't 
           * access methods, computed, data or props of the component.
           * You'd need to make it an arrow function to access the component scope
           */
        })
      }
    }
    

    Whereas in any method (e.g: the above myFn), this is the component context, which has access to all component members.