4

I have been reading the vue documentation and starting to write some code to test my knowledge. I have tried to write a component that sets a data member when mounted but it seems not to work as expected. The component data member "profiles" is always empty. My intuition says it could be something about scope but not sure:

Vue.component('profile-grid', 
{
    template: '<section> {{profiles}} </section>',
    //Data es la parte privada del documento. Props la parte publica que se deberia de pasar desde la instancia Vue
    data: () =>
    {
        return {
            profiles: []
        };
    },
    methods:
    {
    },
    created: () =>
    {
        //console.log("I was just created")
    },
    mounted: () =>
    {
        //console.log("I was just mounted")
        this.profiles = ['1', '2', '3'];     
    }

})

//Vue instance
new Vue(
{
    el:'main',
    data:
    {
    },
    methods:
    {
    },
    mounted: () =>
    {
    }

});

HTML Page

//HTML Page
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Page Title</title>
</head>

<body>
    <main>
        <profile-grid></profile-grid>
    </main>
</body>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="main.js"></script>

</html>

Do anybody know what is happening?

Thanks in advance.

Notbad
  • 5,936
  • 12
  • 54
  • 100

2 Answers2

8

Don't declare Vue hooks, methods and etc as arrow functions. Arrow function use this from parent context.

An arrow function does not have its own this; the this value of the enclosing execution context is used.

You should use method definition syntax or function declaration to be able use this as Vue instance:

mounted: function() {
    //do something
}

OR

mounted() {
    //do something
}

See Vue docs notice in the bottom of the section.

tony19
  • 125,647
  • 18
  • 229
  • 307
Max Sinev
  • 5,884
  • 2
  • 25
  • 35
5

You have stumbled upon one of vuejs reactivity caveats. Basically you are replacing the original profiles in a way that Vuejs cant react to, thus it is not getting updated.

One way to notice the change in the array is to first assign the data property as null and assign a Array in the mounted method later. Another way you can update a reactive Array later is to use array mutation method like push or non mutation method like map to generate a new array and replace the older array with new one.

Vue.component('profile-grid', {
    template: `
        <section> 
          <div>{{profiles && profiles.length ? profiles : ''}} </div>
          <div>{{profilesTwo && profilesTwo.length ? profilesTwo : ''}}</div>
        </section>`,
    data () {
        return {
            profiles: null,
            profilesTwo: []

        };
    },
    created () {
        //console.log("I was just created")
    },
    mounted () {
        //console.log("I was just mounted")
        this.profiles = ['1', '2', '3'];  
        this.profilesTwo = ['5', '4', '6'].map(item => item)   
    }

});

new Vue({
    el:'#app',
    data () {
      return {}
    },
    mounted () {
      console.log('vue instance mounted');
    } 
});
<script src="https://unpkg.com/vue"></script>

<main id="app">
    <profile-grid></profile-grid>
</main>
tony19
  • 125,647
  • 18
  • 229
  • 307
slumbergeist
  • 1,438
  • 12
  • 18