web-dev-qa-db-fra.com

Mettre à jour le composant VueJs lors du changement de route

Existe-t-il un moyen de restituer un composant lors d'un changement de route? J'utilise Vue Router 2.3.0, et j'utilise le même composant dans plusieurs routes. Cela fonctionne très bien la première fois ou si je navigue vers une route qui n'utilise pas le composant, puis allez à celui qui fait. Je passe ce qui est différent dans les accessoires comme si

{
  name: 'MainMap',
  path: '/',
  props: {
    dataFile: 'all_resv.csv',
    mapFile: 'contig_us.geo.json',
    mapType: 'us'
  },
  folder: true,
  component: Map
},
{
  name: 'Arizona',
  path: '/arizona',
  props: {
    dataFile: 'az.csv',
    mapFile: 'az.counties.json',
    mapType: 'state'
  },
  folder: true,
  component: Map
}

Ensuite, j'utilise les accessoires pour charger une nouvelle carte et de nouvelles données, mais la carte reste la même que lors de son premier chargement. Je ne sais pas ce qui se passe.

Le composant ressemble à ceci:

data() {
  return {
    loading: true,
    load: ''
  }
},

props: ['dataFile', 'mapFile', 'mapType'],

watch: {
    load: function() {
        this.mounted();
    }
},

mounted() {
  let _this = this;
  let svg = d3.select(this.$el);

  d3.queue()
    .defer(d3.json, `static/data/maps/${this.mapFile}`)
    .defer(d3.csv, `static/data/stations/${this.dataFile}`)
    .await(function(error, map, stations) {
    // Build Map here
  });
}
13
user1627827

La solution alternative à cette question gère cette situation dans plus de cas.

Tout d'abord, vous ne devriez pas vraiment appeler mounted() vous-même. Résumé de ce que vous faites dans mounted dans une méthode que vous pouvez appeler à partir de mounted. Deuxièmement, Vue essaiera de réutiliser les composants quand il le pourra, donc votre problème principal est probable que mounted n'est déclenché qu'une seule fois. Au lieu de cela, vous pouvez essayer d'utiliser le updated ou beforeUpdatecycle de vie événement.

const Map = {
  data() {
    return {
      loading: true,
      load: ''
    }
  },
  props: ['dataFile', 'mapFile', 'mapType'],
  methods:{
    drawMap(){
        console.log("do a bunch a d3 stuff")
    }
  },
  updated(){
    console.log('updated')
    this.drawMap()
  },
  mounted() {
    console.log('mounted')
    this.drawMap()
  }
}

Voici un petit exemple , ne dessinant pas le truc d3, mais montrant comment mounted et updated sont tirés lorsque vous échangez des routes. Ouvrez la console et vous verrez que mounted n'est déclenché qu'une seule fois.

9
Bert

Vous souhaiterez peut-être ajouter un attribut: key à <router-view> ainsi:

<router-view :key="$route.fullPath"></router-view>

De cette façon, Vue Router rechargera le composant une fois le chemin changé. Sans la clé, il ne remarquera même pas que quelque chose a changé parce que le même composant est utilisé (dans votre cas, le Composant cartographique).

35
Matthias Hagemann

Ceci est l'ancienne réponse, la dernière réponse est ci-dessous

Ma solution à ce problème était de regarder la propriété $route.
Ce qui vous a permis d'obtenir deux valeurs, soit to et from.

watch: {
  '$route'(to, from) {
    const id = to.params.id
    this.AJAXRequest(id)
  }
},

MISE À JOUR --- 3 juillet 2019

Le principe est le même que ci-dessus, mais il s'avère que j'ai trouvé cette chose sur la documentation de vue-router, elle s'appelle In Component Guards . Par sa description, il correspond vraiment à vos besoins (et aux miens en fait). Donc, les codes devraient être quelque chose comme ça.

export default () {
  beforeRouteUpdate (to, from, next) {
    // called when the route that renders this component has changed,
    // but this component is reused in the new route.
    // For example, for a route with dynamic params `/foo/:id`, when we
    // navigate between `/foo/1` and `/foo/2`, the same `Foo` component instance
    // will be reused, and this hook will be called when that happens.
    // has access to `this` component instance.

    const id = to.params.id
    this.AJAXRequest(id)
    next()
  },
}

Comme vous pouvez le voir, j'ajoute juste une fonction next(). J'espère que cela vous aide! Bonne chance!

4
Irfandy Jip