面试题答案
一键面试路由配置
- 定义动态路由参数:在
router/index.js
中,为商品详情页定义动态路由。例如:
const router = new VueRouter({
routes: [
{
path: '/product/:productId',
name: 'ProductDetail',
component: ProductDetail
}
]
});
这里 :productId
是动态参数,用于标识不同的商品。
组件生命周期钩子函数
- 在
beforeRouteEnter
中预取数据:在ProductDetail
组件中,使用beforeRouteEnter
钩子函数。这个钩子函数在路由进入组件之前被调用,且此时组件实例还未被创建,所以不能使用this
。可以通过next
回调函数将预取的数据传递给组件。
export default {
name: 'ProductDetail',
data() {
return {
productData: null,
relatedData: null
};
},
beforeRouteEnter(to, from, next) {
const productId = to.params.productId;
// 预取关键数据的逻辑,这里假设使用 axios 进行请求
import axios from 'axios';
axios.all([
axios.get(`/api/product/${productId}`),
axios.get(`/api/related/${productId}`)
]).then(axios.spread((productRes, relatedRes) => {
next(vm => {
vm.productData = productRes.data;
vm.relatedData = relatedRes.data;
});
})).catch(error => {
// 处理预取数据失败的情况,这里简单提示错误
next(error.message);
});
},
created() {
// 如果在 beforeRouteEnter 中传递了错误信息,在这里处理
if (typeof this.$route.params.error ==='string') {
console.error('数据预取失败:', this.$route.params.error);
}
}
};
数据请求逻辑
- 封装API请求:将数据请求逻辑封装成独立的函数,以便复用。例如:
import axios from 'axios';
export const getProduct = (productId) => {
return axios.get(`/api/product/${productId}`);
};
export const getRelated = (productId) => {
return axios.get(`/api/related/${productId}`);
};
然后在 beforeRouteEnter
中调用这些函数:
import { getProduct, getRelated } from '@/api/product';
beforeRouteEnter(to, from, next) {
const productId = to.params.productId;
axios.all([
getProduct(productId),
getRelated(productId)
]).then(axios.spread((productRes, relatedRes) => {
next(vm => {
vm.productData = productRes.data;
vm.relatedData = relatedRes.data;
});
})).catch(error => {
next(error.message);
});
}
处理预取数据失败的情况
- 在
beforeRouteEnter
中捕获错误:如上述代码,在axios.all
的catch
块中捕获预取数据的错误,并通过next
传递错误信息。 - 在组件
created
钩子中处理错误:在组件的created
钩子函数中检查是否有错误传递过来,并进行相应处理,例如记录错误日志、显示错误提示等。 - 用户体验优化:可以在页面上显示一个加载动画,直到数据预取完成或失败。如果预取失败,可以提供一个重试按钮,让用户重新尝试预取数据。例如,在模板中添加:
<template>
<div>
<div v-if="loading">加载中...</div>
<div v-if="error" class="error">{{ error }}</div>
<button v-if="error" @click="retryFetch">重试</button>
<div v-if="productData && relatedData">
<!-- 商品详情内容展示 -->
</div>
</div>
</template>
export default {
data() {
return {
loading: true,
error: null,
productData: null,
relatedData: null
};
},
beforeRouteEnter(to, from, next) {
const productId = to.params.productId;
axios.all([
getProduct(productId),
getRelated(productId)
]).then(axios.spread((productRes, relatedRes) => {
next(vm => {
vm.loading = false;
vm.productData = productRes.data;
vm.relatedData = relatedRes.data;
});
})).catch(error => {
next(vm => {
vm.loading = false;
vm.error = error.message;
});
});
},
methods: {
retryFetch() {
this.loading = true;
this.error = null;
const productId = this.$route.params.productId;
axios.all([
getProduct(productId),
getRelated(productId)
]).then(axios.spread((productRes, relatedRes) => {
this.loading = false;
this.productData = productRes.data;
this.relatedData = relatedRes.data;
})).catch(error => {
this.loading = false;
this.error = error.message;
});
}
}
};