В настоящее время я использую WordPress REST API и vue-router для перехода между страницами на небольшом одностраничном сайте. Однако когда я выполняю AJAX-вызов на сервер с использованием REST API, данные загружаются, но только после того, как страница уже обработана.

документация vue-router дает представление о том, как загружать данные до и после навигации по каждому маршруту, но я хотел бы знать, как загрузить все данные маршрута и страницы при начальной загрузке страницы, чтобы обойти необходимость загрузки данных каждый раз при активации маршрута.

Обратите внимание, я загружаю свои данные в свойство acf, а затем обращаюсь к ним в файловом компоненте .vue, используя this.$parent.acfs.

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')

Код компонента Home.vue:

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

Есть идеи?

43
10000RubyPools 10 Янв 2017 в 18:56

4 ответа

Лучший ответ

Хорошо, я наконец понял это. Все, что я делаю, это вызывает синхронный запрос ajax в моем файле main.js, в котором создается экземпляр моего корневого экземпляра, и присваиваем свойству данных запрошенные данные следующим образом:

< Сильный > 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')

Отсюда я могу использовать извлеченные данные в каждом отдельном файле / компоненте .vue следующим образом:

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

Наконец, я отображаю данные в том же шаблоне .vue со следующим:

<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>

Самая важная часть информации, которую нужно забрать, состоит в том, что все данные ACF в самом начале называются ОДИН РАЗ, по сравнению с каждым разом, когда маршрут посещается с использованием чего-то вроде beforeRouteEnter (to, from, next). В результате я могу получить плавные переходы страниц по желанию.

Надеюсь, это поможет тому, кто столкнется с той же проблемой.

3
10000RubyPools 11 Янв 2017 в 01:43

Проверьте этот раздел в документах Vue Router

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

Поэтому сначала вам нужно написать метод, который будет извлекать данные из вашей конечной точки, а затем использовать watcher для отслеживания маршрута.

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

Поскольку вы работаете с WP Rest API, не стесняйтесь проверять мой репозиторий на Github https://github.com/bedakb/vuewp/blob/master/public/app/themes/vuewp/app/views/PostView.vue#L39

3
Skoua 12 Июн 2018 в 04:22

Мой подход заключается в том, чтобы отложить строительство магазина и главного Vue до тех пор, пока не вернется мой вызов 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 },
    });
  });

Я использовал этот подход с другими фреймворками, такими как Angular и ExtJS.

53
Miguel 26 Авг 2017 в 21:02

Вы можете использовать средства защиты навигации.

На конкретном компоненте это будет выглядеть так:

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

Вы также можете добавить навигационную охрану ко всем компонентам:

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

Следует помнить, что средства навигации являются асинхронными, поэтому вам нужно вызвать обратный вызов next(), когда загрузка данных будет завершена. Реальный пример из моего приложения (где функция защиты находится в отдельном файле):

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

В вашем случае вам, конечно, нужно позвонить next() в success обратном вызове.

4
mingos 10 Янв 2017 в 16:08