web-dev-qa-db-fra.com

méthode montée est déclenchée avant le chargement des données - VueJS

J'utilise Vue Resource pour récupérer une collection d'images à partir d'une API REST. La demande est envoyée dans le hook created de mon composant Vue. 

Le problème est que j'essaie d'accéder aux données extraites via le hook mounted, mais les données ne sont pas chargées. 

Je reçois cette erreur dans la console:

[Vue warn]: Erreur dans le crochet monté: "TypeError: Impossible de lire la propriété 'forEach' of indéfinie"

Voici mon composant:

<script>
export default {
  data() {
    return { imgs : '' };
  },
  created() {
    // the full url is declare in my main.js
    this.imgs = this.$resource('acf/v3/pages/4');

    this.imgs.query().then((response) => {
      console.log('success', response);
      this.imgs = response.data.acf.gallery;
    }, (response) => {
      console.log('erreur', response);
    });
  },
  mounted() {
    // get the ref="image" in my dom template
    let imgs = this.$refs.image;

    imgs.forEach((img) => {
      // I do some stuff with imgs
    });
  }
}
</script>

Si j'emballe une setTimeout autour du contenu de mounted, tout fonctionne correctement. 

Donc, je ne comprends pas comment je peux attendre que mes données se chargent avant que le hook mounted ne soit exécuté. N'est-ce pas le rôle des crochets du cycle de vie Vue? 

6
BrownBe

Puisque l'appel this.imgs.query() est asynchrone, votre hook mounted est appelé avant que le gestionnaire then ne définisse this.imgs (ce qui, je suppose, est lié à v-for à un élément de votre modèle avec un attribut ref="image"). Ainsi, même si le composant a été monté sur le DOM, le $refs n'a pas encore été configuré.

Je ferais une méthode pour "faire des choses avec imgs" et ensuite appeler cette méthode dans un $nextTick callback dans le gestionnaire then de l'appel async. Le rappel transmis à $nextTick sera "exécuté après le prochain cycle de mise à jour du DOM", ce qui signifie que le $refs sera configuré à ce stade.

<script>
export default {
  data() {
    return { imgs: '' };
  },
  created() {
    // the full url is declare in my main.js
    this.imgs = this.$resource('acf/v3/pages/4');

    this.imgs.query().then((response) => {
      console.log('success', response);
      this.imgs = response.data.acf.gallery;
      this.$nextTick(() => this.doStuffWithImgs());
    }, (response) => {
      console.log('erreur', response);
    });
  },
  methods: {
    doStuffWithImgs() {
      // get the ref="image" in my dom template
      let imgs = this.$refs.image;

      imgs.forEach((img) => {
        // I do some stuff with imgs
      });
    }
  }
}
</script>
4
thanksd

Comme indiqué dans le Lifecycle Diagram of Instance Vue. Après Mounted Hook (ce qui signifie que nous pouvons accéder au DOM), il existe également des hooks beforeUpdate et mis à jour. Ces crochets peuvent être utilisés lorsque les données sont modifiées. Je pense que beforeUpdate ou le hook de mise à jour peut être utilisé après avoir récupéré les données dans le hook créé.

<script>
   export default {
      data() {
         return { imgs : '' };
       },
   created() {
    // the full url is declare in my main.js
    this.imgs = this.$resource('acf/v3/pages/4');

    this.imgs.query().then((response) => {
        console.log('success', response);
        this.imgs = response.data.acf.gallery;
       }, (response) => {
         console.log('erreur', response);
     });
   },
  // here we can use beforeUpdate or updated hook instead of mounted
  beforeUpdate() {
    // get the ref="image" in my dom template
    let imgs = this.$refs.image;

    imgs.forEach((img) => {
    // I do some stuff with imgs
   });
 }
}

J'espère que ça aide. 
Je rappelle que je suis nouveau pour VueJS et que j'apprends de nos jours). 

1
bakhti_uzb