SoFunction
Updated on 2025-04-04

Interpretation of three usages of $refs in vue

Three usages of vue $refs

We all know that if you get the DOM element in vue2, you can directly bind the ref attribute on the element and then get the attribute value of the DOM element. This method can still be used in vue3, but there will be some problems.

Here are three usages of $refs:

1. In vue2

In vue2, we can directly use ref to get the element, that is, we can directly bind the ref attribute on the element, and directly use this.$refs['custom attribute name'] to get it.

But this also has certain risks. Because the ref is bound to the element, when the element is not rendered, the element cannot be obtained through the ref.

<template>
  <div>
    <div ref="btn">I'm a button</div>
  </div>
</template>
 
<script>
 
export default {
  name: 'App',
  created() {
    //Use this.$refs directly to get the DOM element    (this.$); // undefined
    this.$nextTick(() => {
        (this.$)  //Get the correct element    })
  },
  mounted() {
    (this.$); //Get the correct element  }
}
</script>

It should be noted that when using this method to obtain the elements of v-for in vue2, the array is obtained.

<template>
  <div>
    <div ref="btn" v-for="(item , index) in 3" :key="index">I'm a button</div>
  </div>
</template>
 
<script>
 
export default {
  name: 'App',
  mounted() {
    //What I got is an array of elements    (this.$); 
  }
}
</script>

2. In vue3

In general, the method of obtaining elements of vue2 is also fully applicable in vue3.

However, sometimes you may encounter the inability to obtain this node because of the life cycle problem. In vue3, the original created is gone, and the setup acts as the original created.

Therefore, when setting up, the dom element has not been created yet. Only after the setup is completed can the HTML be built, and the value value can be truly accessed, so naturally the dom node cannot be obtained. To solve this problem, you must cooperate with the hook function onMounted and obtain it after the dom is mounted.

<template>
    <div >
        <!--Use on elements ref="butRef" Bind-->
        <button type="button" ref="butRef" >Button Element</button>
    </div>
</template>
 
<script>
    //Introduce ref    import {ref, onMounted} from 'vue'
    export default {
        setup() {
 
            //You need to define butRef first            let butRef = ref(null)
            onMounted(()=>{
              //When used, it is (requires the value of the DOM element)              ();
            })
            return {
                butRef
            }
        }
    }
</script>

3. Vue3's combination API (composition-api)

The last method is to deconstruct refs from the context Ctx (context). Although refs may prompt that they have been deprecated, they are still usable here.

<template>
    <div >
        <button type="button" ref="butRef" >Button Element</button>
    </div>
</template>
 
<script lang="ts">
import { defineComponent, ref, watch } from '@vue/composition-api';
 
export default defineComponent({
    name: '',
    components: {},
    setup (props, ctx) {
        //Deconstruct refs from Ctx (context)        const { emit, refs } = ctx;
            
        watch(filterText, (val) => {
            //Use it directly when using it            //(val);
            ( as Any).filter(val);
        });
        return {
            butRef
        }
    }
}
</script>

Understanding $refs in vue

$refs is an object that holds all DOM elements and component instances that have registered the ref attribute.

describe

Ref is used to register reference information for elements or children, and the reference information will be registered on the $refs object of the parent component.

If used on a normal DOM element, the reference points to the DOM element;

If used on a child component, the reference points to the component instance.

In addition, when v-for is used for elements or components, the reference information will be an array containing DOM nodes or component instances.

<!DOCTYPE html>
<html>
<head>
    <title>Vue</title>
</head>
<body>
    <div >
        <div ref="node">Node</div>
        <layout-div ref="layout"></layout-div>
        <div v-for="i in 3" :key="i" ref="nodearr">{{i}}</div>
    </div>
</body>
<script src="/vue/2.4.2/"></script>
<script type="text/javascript">
    ("layout-div", {
      data: function(){
          return {
            count: 0
          }
      },
      template: `<div>
                    <div>{{count}}</div>
                </div>`
    })
 
    var vm = new Vue({
        el: '#app',
        mounted: function(){
            (this.$); // <div>Node</div> // DOM element            (this.$); // VueComponent {_uid: 1, ...} // Component instance            (this.$); // (3) [div, div, div] // DOM element array        }
    })
&lt;/script&gt;
&lt;/html&gt;

Because ref itself is created as a rendering result and cannot be accessed during initial rendering, because it does not exist yet, and $refs is not responsive, so it should not be attempted to use it to do data binding in the template. When initially accessing ref, it should be called in the mounted method of its life cycle. After data update, a callback operation should be passed in the $nextTick method to obtain elements or instances. In addition, it is generally not recommended to operate DOM elements directly. Try to use data binding to let the MVVM's ViewModel operate the DOM.

<!DOCTYPE html>
<html>
<head>
    <title>Vue</title>
</head>
<body>
    <div ></div>
</body>
<script src="/vue/2.4.2/"></script>
<script type="text/javascript">
 
    var vm = new Vue({
        el: '#app',
        data: function(){
            return {
                msg: 0
            }
        },
        template:  `<div>
                       <div ref="node">{{msg}}</div>
                       <button @click="updateMsg">button</button>
                    </div>`,
        beforeMount: function(){
            (this.$); // undefined
        },
        mounted: function(){
            (this.$); // <div>0</div>
        },
        methods: {
            updateMsg: function(){
                 = 1;
                (this.$); // 0
                this.$nextTick(() => {
                    (this.$); // 1
                })
            }
        }
    })
</script>
</html>

Summarize

The above is personal experience. I hope you can give you a reference and I hope you can support me more.