web-dev-qa-db-fra.com

Vuejs ne peut pas accéder aux références depuis le composant

J'essaie d'obtenir l'élément canvas qui se trouve dans le modèle d'un composant. Nous avons trouvé d'excellentes documentations pour vuejs1, mais pas pour vuejs2, où "ref" est le seul moyen d'obtenir l'élément. Je reçois l'objet cependant, mais lorsque j'essaie d'accéder à la variable, il n'est pas défini. 

Mon html

<div id="app>
  <template id="image-capture">
    <div class="row" >
      <canvas ref="icanvas" ></canvas>
    </div>
  </template>
</div>

Mon js

const ic = {
  template: '#image-capture' ,

  created () {
    console.log(this.$refs); //this returns object
    console.log(this.$refs.icanvas); // but this is undefined
  }


}

const routes = [
  { path: '/ic', component:   ic},
]

const router = new VueRouter({
  routes 
})

 new Vue({
  router,
   }).$mount('#app')

Je dois obtenir l'élément icanvas.

 here is console log

21
Code Tree

La created est déclenchée avant le traitement du modèle.
Vous trouverez plus de détails ici: https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

Vous devriez pouvoir accéder aux $ ref sur l’événement mounted

mounted: function() {
    console.log(this.$refs.icanvas);
},
24
Mihai Vilcu

Vous pouvez utiliser la fonction $ nextTick (), le code contenu dans $ nextTick () sera exécuté après la mise à jour du DOM.

this.$nextTick(function () {

    console.log(this.$refs.ANY_COMPONENT_REF)

})
6
Kishan Madhesiya

j'ai eu exactement le même problème, dans mon cas je l'ai résolu en accédant à la référence dans la méthode qui modifie le v-if avec nextTick.

methods: {
open() {
  this.show = true; //v-if condition
    this.$nextTick(function() {
      this.titleWidth = this.$refs.titleBg.clientWidth - 30;
    });
}
1
Dan Levin

Normalement, vous pouvez accéder à la référence mounted, comme @Mihai Vilcu posté:

mounted: function() {
    console.log(this.$refs.icanvas);
}

Cependant, comme l'a dit @BrownBe, 

c'est toujours un problème si vos références sur un élément v-pour. Le DOM n'est pas en mesure d'accéder à cette référence lorsque le crochet monté est déclenché.

Jusqu'au 2018.10.27, la question était toujours d'actualité, et voici les derniers problèmes

La raison peut être trouvée ici

Une remarque importante sur le calendrier d’enregistrement des références: car les références elles-mêmes sont créées à la suite de la fonction de rendu, vous ne pouvez pas accédez-y au rendu initial - ils n’existent pas encore!

Et voici ce que je fais pour résoudre cette question:

  mounted() {
    this.$_xsl__watchRefs(this.$el, '.lazy_image').then(refs => {
      //do something with `refs`
    })
  }

Et voici le $_xsl__watchRefs 

   $_xsl__watchRefs(targetNode, refsSelector) {
      return new Promise(function(resolve) {
        let observer = new MutationObserver(callback)
        let config = { childList: true, subtree: true }
        observer.observe(targetNode, config)

        function callback(mutationsList, observer) {
          mutationsList.forEach(mutation => {
            if (mutation.type == 'childList') {
              let refs = targetNode.querySelectorAll(refsSelector)
              if (refs.length !== 0) {
                observer.disconnect()
                resolve(Array.from(refs))
              }
            }
          })
        }
      })
    }

Vous pouvez le modifier selon vos besoins. Voici MutationObserver qui supportait IE11 +. 

Un autre choix facile. Supposons que vous utilisiez v-for comme:

<li class="list__item" v-for="(item,index) in pubList" :key="index">
   <img
      class="list__img lazy_image"
      ref="lazyImages"
    >
</li>

Et 

 props: ['pubList'],

Dans ce cas, vous pouvez essayer:

  watch: {
    'pubList.length': function() {
      this.$nextTick(function() {
        console.log(this.$refs.lazyImages)
      })
    }
  },

Dans certains cas, les deux méthodes ne fonctionneront pas car this.$refs.lazyImages existait déjà. Donc, la méthode la plus sûre est:

  mounted() {
    if (this.$refs.lazyImages) {
      //do something with `this.$refs.lazyImages`
    } else {
      this.$_xsl__watchRefs(this.$el, '.lazy_image').then(refs => {
        //do something with `refs`
      })
    }
  },
0
xianshenglu