面试题答案
一键面试避免重复请求
- 使用缓存
- 思路:在Vue组件外创建一个缓存对象,用于存储已经请求过的数据。在组件的
created
或beforeMount
钩子中,在发起请求前先检查缓存。如果缓存中已有对应数据,则直接使用缓存数据,避免重复请求。 - 示例代码:
const dataCache = {}; export default { data() { return { dataFromApi: null }; }, created() { const cacheKey = 'your - api - key'; if (dataCache[cacheKey]) { this.dataFromApi = dataCache[cacheKey]; } else { // 发起异步请求 this.$axios.get('/your - api - url') .then(response => { this.dataFromApi = response.data; dataCache[cacheKey] = response.data; }); } } };
- 思路:在Vue组件外创建一个缓存对象,用于存储已经请求过的数据。在组件的
- 共享数据组件
- 思路:将数据请求逻辑封装到一个共享组件中,其他需要该数据的组件通过props或Vuex等状态管理工具获取数据。这样可以保证数据只请求一次,多个组件复用该数据。
- 示例代码(使用Vuex):
- Vuex store.js
import Vue from 'vue'; import Vuex from 'vuex'; import axios from 'axios'; Vue.use(Vuex); const state = { sharedData: null }; const mutations = { SET_SHARED_DATA(state, data) { state.sharedData = data; } }; const actions = { async fetchSharedData({ commit }) { const response = await axios.get('/your - api - url'); commit('SET_SHARED_DATA', response.data); return response.data; } }; export default new Vuex.Store({ state, mutations, actions });
- 组件中使用
<template> <div> {{ sharedData }} </div> </template> <script> export default { computed: { sharedData() { return this.$store.state.sharedData; } }, created() { if (!this.sharedData) { this.$store.dispatch('fetchSharedData'); } } }; </script>
处理并发请求
- 使用Promise.all
- 思路:当多个组件需要同时发起异步请求时,可以将这些请求的Promise对象收集到一个数组中,然后使用
Promise.all
方法。Promise.all
会等待所有Promise都完成(或其中一个失败),这样可以避免不必要的竞争和重复请求,并且能更高效地管理多个并发请求。 - 示例代码:
export default { data() { return { data1: null, data2: null }; }, created() { const promise1 = this.$axios.get('/api/data1'); const promise2 = this.$axios.get('/api/data2'); Promise.all([promise1, promise2]) .then(([response1, response2]) => { this.data1 = response1.data; this.data2 = response2.data; }); } };
- 思路:当多个组件需要同时发起异步请求时,可以将这些请求的Promise对象收集到一个数组中,然后使用
- 限制并发数
- 思路:如果并发请求过多可能会导致性能问题,可以通过控制并发请求的数量来优化。可以使用队列的方式,将请求依次放入队列,按照一定的并发数依次执行请求。
- 示例代码(使用简单队列和定时器模拟):
const requestQueue = []; const maxConcurrent = 2; let currentCount = 0; function enqueueRequest(request) { requestQueue.push(request); processQueue(); } function processQueue() { while (currentCount < maxConcurrent && requestQueue.length > 0) { const request = requestQueue.shift(); currentCount++; request() .then(() => { currentCount--; processQueue(); }); } } export default { data() { return { data1: null, data2: null }; }, created() { enqueueRequest(() => this.$axios.get('/api/data1') .then(response => { this.data1 = response.data; })); enqueueRequest(() => this.$axios.get('/api/data2') .then(response => { this.data2 = response.data; })); } };
在Vue生命周期钩子函数中,created
钩子通常是发起异步数据请求的最佳时机,因为此时组件实例已经创建,数据观测和事件机制都已就绪,但DOM还未挂载,所以不会阻塞DOM渲染。beforeMount
钩子也可以用于发起请求,但相比之下,created
钩子更靠前,能更早地开始数据加载,减少用户等待时间。如果数据请求依赖于DOM元素(虽然不常见),可以在mounted
钩子中发起请求,但要注意避免阻塞页面渲染。