我目前正在使用WordPress REST API和vue-router在小型单页网站上的页面之间进行转换。但是,当我使用REST API对服务器进行AJAX调用时,数据会加载,但只有在页面已经呈现之后才会加载。
vue-router documentation提供了有关如何在导航到每个路径之前和之后加载数据的见解,但我想知道如何在初始页面加载时加载所有路径和页面数据,环绕需求每次激活路线时加载数据。
注意,我正在将我的数据加载到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,
}
},
}
有什么想法吗?
答案 0 :(得分:39)
我的方法是延迟商店和主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。
答案 1 :(得分:3)
在Vue Router的文档中查看此部分
https://router.vuejs.org/guide/advanced/data-fetching.html
所以你们首先必须编写从端点获取数据的方法,然后使用观察者来观察路由。
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
答案 2 :(得分:2)
您可以使用navigation guards。
在特定组件上,它看起来像这样:
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
。
答案 3 :(得分:2)
好吧,我终于想出了这件事。我正在做的就是在我的main.js
文件中调用同步ajax请求,我的root vue实例被实例化,并为数据属性分配所请求的数据:
<强> 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数据一开始只被称为ONCE,而每次使用类似beforeRouteEnter (to, from, next)
的访问路径时都是如此。因此,我可以根据需要获得丝般顺畅的页面转换。
希望这可以帮助遇到同样问题的人。
答案 4 :(得分:2)
我根据对本帖子的所有好评做出了自己的版本。.几年过去了,还为我提供了更多工具。
在 main.js 中,我使用async / await调用预取服务来加载启动时必须存在的所有数据。我发现这提高了可读性。获得数据 comms 后,我将其分派到beforeCreate()挂钩中的相应vuex存储模块中。
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import { prefetchAppData } from '@/services/prefetch.service';
(async () => {
let comms = await prefetchAppData();
new Vue({
router,
store,
beforeCreate() {
store.dispatch('communityModule/initialize', comms);
},
mounted() {},
render: h => h(App)
}).$mount('#app');
})();
我不得不警告那些要小心的人。尝试谨慎地执行此操作,因为它会延迟初始应用程序加载,这对于获得良好的用户体验而言并不理想。
这是我的示例 prefetch.service.js ,它会加载数据。当然,这可能会更复杂。
import api from '@api/community.api';
export async function prefetchAppData() {
return await api.getCommunities();
}
一个简单的vue商店。该商店维护着一个“社区”列表,该列表要求在应用程序启动之前必须先加载该应用程序。
community.store.js (请注意,我使用vuex模块)
export const communityModule = {
namespaced: true,
state: {
communities: []
},
getters: {
communities(state) {
return state.communities;
},
},
mutations: {
SET_COMMUNITIES(state, communities) {
state.communities = communities;
}
},
actions: {
// instead of loading data here, it is passed in
initialize({ commit }, comms) {
commit('SET_COMMUNITIES', comms);
}
}
};