Search code examples
vue.jscomponentsundefinedrefvue-directives

Trying to use ref inside a Vue single file component. Got undefined


I'm beginning with vuejs and I try to figure what could be done about reference of child component instance in root instance. I used ref attribute and it works pretty well, except if I use it in a single file component (in the template tags). In this specific case, I get 'undefined'.

So, I try to understand why, because it could be very useful for establishing dynamic references. I could probably bypass that situation easily, but I would like to understand the problem instead of run away.

So if someone have an idea ;)

I am using webpack to import my single file component in my app.js and compiled it. However the template compilation isn't done by webpack, but by the browser at runtime (maybe it's the beginning of an explanation ?).

My app is very simple, and I log my references on click on the header, so I don't think it's lifecylce callback related.

Here is my files :

app.js

import Vue from 'Vue';
import appButton from './appButton.vue';
import appSection from './appSection.vue';


var app = new Vue({
    el: '#app',
    components:
    {
        'app-button' : appButton
    },
    methods:
    {
        displayRefs: function()
        {
            console.log(this.$refs.ref1);
            console.log(this.$refs.ref2);
            console.log(this.$refs.ref3);
        }
    }
});

my component appButton.vue

<template>
    <div ref="ref3" v-bind:id="'button-'+name" class="button">{{label}}</div>
</template>


<script>

    module.exports = 
    {
        props: ['name', 'label']
    }

</script>

my index.html body

<body>

    <div id="app">

        <div id="background"></div>

        <div id="foreground">

            <img id="photo" src="./background.jpg"></img>

            <header ref="ref1">
                    <h1 v-on:click="displayRefs">My header exemple</h1>
            </header>


            <nav>
                <app-button ref="ref2" name="presentation" label="Qui sommes-nous ?"></app-button>
            </nav>

        </div>

    </div>

    <script src="./app.js"></script>

</body>

ref1 (header tag) and ref2 (app-button tag) are both found. But ref3 (in my single file component) is undefined. Also

Thanks for all the piece of answer you could give me, hoping it's not a silly mistake.


Solution

  • A ref you set is only accessible in the component itself.

    If you try to console.log(this.$refs.ref3); into a method from appButton.vue, it will work. But it won't work in the parent.

    If you want to access that ref from the parent, you need to use the $ref2 to access the component, and then use the $ref3. Try this:

    var app = new Vue({
        el: '#app',
        components:
        {
            'app-button' : appButton
        },
        methods:
        {
            displayRefs: function()
            {
                console.log(this.$refs.ref1);
                console.log(this.$refs.ref2);
                console.log(this.$refs.ref2.$refs.ref3); // Here, ref3 will be defined.
            }
        }
    });
    

    Accessing some child ref from the parent is not supposed to be a good practice tho.