web-dev-qa-db-fra.com

Comment charger toutes les données côté serveur lors du chargement initial de vue.js / vue-router?

J'utilise actuellement l'API WordPress REST, et vue-router) pour passer d'une page à une autre sur un petit site à une seule page. un appel AJAX au serveur à l'aide de l'API REST, les données sont chargées, mais uniquement après que la page a été rendue.

Le documentation de vue-router explique comment charger des données avant et après la navigation vers chaque route, mais j'aimerais savoir comment charger toutes les données de route et de page sur le chargement de page initial, circumnavigating la nécessité de charger des données chaque fois qu'un itinéraire est activé.

Notez que je charge mes données dans la propriété acf, puis que j'y accède dans un fichier .vue composant du fichier utilisant this.$parent.acfs.

Code du routeur main.js:

const router = new VueRouter({
    routes: [
        { path: '/', component: Home },
        { path: '/about', component: About },
        { path: '/tickets', component: Tickets },
        { path: '/sponsors', component: Sponsors },
    ],
    hashbang: false
});

exports.router = router;

const app = new Vue({
    router,
    data: {
        acfs: ''
    },
    created() {
        $.ajax({
            url: 'http://localhost/placeholder/wp-json/acf/v2/page/2',
            type: 'GET',
            success: function(response) {
                console.log(response);
                this.acfs = response.acf;
                // this.backgroundImage = response.acf.background_image.url
            }.bind(this)
        })
    }
}).$mount('#app')

Code du composant Home.vue:

export default {
    name: 'about',
    data () {
        return {
            acf: this.$parent.acfs,
        } 
    },
}

Des idées?

27
10000RubyPools

D'accord, j'ai finalement compris cette chose. Tout ce que je fais est d'appeler une demande ajax synchrone dans mon fichier main.js Où ma racine vue est instanciée) et d'attribuer les données demandées à une propriété de données de la manière suivante:

main.js

let acfData;

$.ajax({
    async: false,
    url: 'http://localhost/placeholder/wp-json/acf/v2/page/2',
    type: 'GET',
    success: function(response) {
        console.log(response.acf);
        acfData = response.acf;
    }.bind(this)
})  

const router = new VueRouter({
    routes: [
        { path: '/', component: Home },
        { path: '/about', component: About },
        { path: '/tickets', component: Tickets },
        { path: '/sponsors', component: Sponsors },
    ],
    hashbang: false
});

exports.router = router;

const app = new Vue({
    router,
    data: {
        acfs: acfData 
    },
    created() {

    }
}).$mount('#app')

À partir de là, je peux utiliser les données extraites dans chaque fichier/composant individuel .vue Comme suit:

export default {
    name: 'app',
    data () {
    return {
        acf: this.$parent.acfs,
    }
},

Enfin, je rends les données dans le même modèle .vue Avec les éléments suivants:

<template>
  <transition
      name="home"
      v-on:enter="enter"
      v-on:leave="leave"
      v-bind:css="false"
      mode="out-in"
    >
    <div class="full-height-container background-image home" v-bind:style="{backgroundImage: 'url(' + this.acf.home_background_image.url + ')'}">
      <div class="content-container">
        <h1 class="white bold home-title">{{ acf.home_title }}</h1>
        <h2 class="white home-subtitle">{{ acf.home_subtitle }}</h2>
        <div class="button-block">
          <a href="#/about"><button class="white home-button-1">{{ acf.link_title_1 }}</button></a>
          <a href="#/tickets"><button class="white home-button-2">{{ acf.link_title_2 }}</button></a>
        </div>
      </div>
    </div>
  </transition>
</template>

L’information la plus importante à retenir est que toutes les données ACF ne sont appelées ONCE qu’au début, par rapport à chaque fois qu’un itinéraire est visité en utilisant quelque chose comme beforeRouteEnter (to, from, next). En conséquence, je peux obtenir des transitions de page soyeuses et lisses comme vous le souhaitez.

J'espère que cela aide quiconque rencontre le même problème.

2
10000RubyPools

Mon approche est de retarder la construction du magasin et principal Vue jusqu'au retour de mon AJAX).

store.js

import Vue from 'vue';
import Vuex from 'vuex';
import actions from './actions';
import getters from './getters';
import mutations from './mutations';

Vue.use(Vuex);

function builder(data) {
  return new Vuex.Store({
    state: {
      exams: data,
    },
    actions,
    getters,
    mutations,
  });
}

export default builder;

main.js

import Vue from 'vue';
import VueResource from 'vue-resource';
import App from './App';
import router from './router';
import store from './store';

Vue.config.productionTip = false;

Vue.use(VueResource);

Vue.http.options.root = 'https://miguelmartinez.com/api/';

Vue.http.get('data')
  .then(response => response.json())
  .then((data) => {
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      router,
      store: store(data),
      template: '<App/>',
      components: { App },
    });
  });

J'ai utilisé cette approche avec d'autres frameworks tels que Angular et ExtJS.

42
Miguel

Vérifiez cette section dans la documentation de Vue Router

https://router.vuejs.org/guide/advanced/data-fetching.html

Donc, vous devez d’abord écrire une méthode qui permettrait de récupérer les données de votre point de terminaison, puis utiliser l’observateur pour surveiller l’itinéraire.

export default {
    watch: {
        '$route': 'fetchItems'
    },
    methods: {
        fetchItems() {
          // fetch logic
        }
    }
}

Puisque vous travaillez avec WP Rest API, n'hésitez pas à consulter mon dépôt sur Github https://github.com/bedakb/vuewp/blob/master/public/app/ themes/vuewp/app/views/PostView.vue # L39

3
Belmin Bedak

Vous pouvez utiliser protecteurs de navigation .

Sur un composant spécifique, cela ressemblerait à ceci:

export default {
    beforeRouteEnter (to, from, next) {
        // my ajax call
    }
};

Vous pouvez également ajouter une protection de navigation à tous les composants:

router.beforeEach((to, from, next) => {
    // my ajax call
});

Une chose à garder à l'esprit est que les protecteurs de navigation sont asynchrones, vous devez donc appeler le rappel next() lorsque le chargement des données est terminé. Un exemple réel de mon application (où la fonction de garde réside dans un fichier séparé):

export default function(to, from, next) {
    Promise.all([
        IngredientTypes.init(),
        Units.init(),
        MashTypes.init()
    ]).then(() => {
        next();
    });
};

Dans votre cas, vous auriez besoin d'appeler next() dans le callback success, bien sûr.

2
mingos