面试题答案
一键面试网络层面
- 缓存策略
- 强缓存:在Vue应用中,可以利用HTTP缓存头(如
Cache - Control
、Expires
)来设置强缓存。例如,对于一些不经常变化的静态数据接口(如网站配置信息),可以设置较长的缓存时间。
// 在后端设置缓存头(以Node.js + Express为例) const express = require('express'); const app = express(); app.get('/config', (req, res) => { res.set('Cache - Control','public, max - age = 3600');// 缓存1小时 res.send({/* 配置信息 */}); });
- 协商缓存:通过
Last - Modified
和ETag
头来实现。当数据可能有变化但变化频率不高时适用。在Vue应用的created
钩子函数中发送请求时,带上If - Modified - Since
(对应Last - Modified
)或If - None - Match
(对应ETag
)头。
// 在Vue组件中 export default { created() { const headers = {}; const lastModified = localStorage.getItem('configLastModified'); if (lastModified) { headers['If - Modified - Since'] = lastModified; } this.$http.get('/config', { headers }).then(response => { if (response.status === 200) { localStorage.setItem('configLastModified', response.headers['last - modified']); // 处理数据 } else if (response.status === 304) { // 从缓存中读取数据 } }); } };
- 强缓存:在Vue应用中,可以利用HTTP缓存头(如
- 请求合并
- 防抖:对于频繁触发的异步请求(如搜索框输入实时搜索),可以使用防抖策略。在Vue中可以通过自定义指令或在方法中使用
setTimeout
实现。
<template> <input v - model="searchText" @input="debouncedSearch"> </template> <script> export default { data() { return { searchText: '', timer: null }; }, methods: { debouncedSearch() { clearTimeout(this.timer); this.timer = setTimeout(() => { this.$http.get('/search', { params: { q: this.searchText } }).then(response => { // 处理搜索结果 }); }, 300); } } }; </script>
- 节流:适用于固定频率触发的请求场景,如滚动加载更多。通过控制请求的频率,避免短时间内多次请求相同数据。
<template> <div @scroll="throttledLoadMore"> <!-- 页面内容 --> </div> </template> <script> export default { data() { return { throttleTimer: null, page: 1 }; }, methods: { throttledLoadMore() { if (!this.throttleTimer) { this.throttleTimer = setTimeout(() => { this.$http.get('/loadMore', { params: { page: this.page } }).then(response => { // 处理加载更多的数据 this.page++; this.throttleTimer = null; }); }, 200); } } } }; </script>
- 防抖:对于频繁触发的异步请求(如搜索框输入实时搜索),可以使用防抖策略。在Vue中可以通过自定义指令或在方法中使用
组件层面
- 数据预取
- 在路由导航守卫中预取:在Vue Router的
beforeEach
守卫中,根据即将进入的路由,提前获取相关数据。例如,在一个博客应用中,当用户点击文章列表中的某篇文章链接时,在进入文章详情页之前,提前获取文章内容。
import router from './router'; import store from './store'; router.beforeEach((to, from, next) => { if (to.name === 'ArticleDetail') { const articleId = to.params.id; store.dispatch('fetchArticle', articleId).then(() => { next(); }); } else { next(); } });
- 在组件生命周期钩子中预取:在组件的
created
或beforeMount
钩子函数中提前获取数据。比如一个商品详情组件,在组件创建时就获取商品的详细信息。
export default { created() { const productId = this.$route.params.productId; this.$http.get(`/products/${productId}`).then(response => { this.product = response.data; }); } };
- 在路由导航守卫中预取:在Vue Router的
- 按需加载
- 动态导入组件:对于一些不常用的组件(如用户设置中的高级设置组件),可以使用动态导入。在Vue中通过
import()
语法实现。
const routes = [ { path: '/settings/advanced', name: 'AdvancedSettings', component: () => import('./components/AdvancedSettings.vue') } ];
- 图片懒加载:在Vue应用中,可以使用
vue - lazyload
插件来实现图片的懒加载。这在展示大量图片的页面(如商品列表页)中很有用。
<template> <div v - for="product in products" :key="product.id"> <img v - lazy="product.imageUrl" alt="Product Image"> <p>{{ product.name }}</p> </div> </template> <script> import VueLazyload from 'vue - lazyload'; export default { data() { return { products: [] }; }, created() { this.$http.get('/products').then(response => { this.products = response.data; }); } }; Vue.use(VueLazyload); </script>
- 动态导入组件:对于一些不常用的组件(如用户设置中的高级设置组件),可以使用动态导入。在Vue中通过
代码层面
- 异步请求并发控制
- 使用
Promise.all
进行并发请求并控制数量:在需要同时获取多个数据但又要控制并发数量的场景下,例如一个电商应用中同时获取商品信息、库存信息和评论数量。假设我们限制并发数为3。
export default { data() { return { productInfo: null, stockInfo: null, reviewCount: null }; }, created() { const requests = [ this.$http.get('/productInfo'), this.$http.get('/stockInfo'), this.$http.get('/reviewCount'), this.$http.get('/otherInfo1'), this.$http.get('/otherInfo2') ]; const maxConcurrent = 3; const results = []; for (let i = 0; i < requests.length; i += maxConcurrent) { const batch = requests.slice(i, i + maxConcurrent); Promise.all(batch).then(values => { results.push(...values); if (results.length === requests.length) { this.productInfo = results[0].data; this.stockInfo = results[1].data; this.reviewCount = results[2].data; // 处理其他结果 } }); } } };
- 使用
async/await
配合队列实现并发控制:可以自己实现一个简单的队列来控制请求并发。
class RequestQueue { constructor(maxConcurrent) { this.maxConcurrent = maxConcurrent; this.queue = []; this.running = 0; } enqueue(request) { return new Promise((resolve, reject) => { this.queue.push({ request, resolve, reject }); this.runNext(); }); } runNext() { while (this.running < this.maxConcurrent && this.queue.length > 0) { const { request, resolve, reject } = this.queue.shift(); this.running++; request().then(response => { resolve(response); this.running--; this.runNext(); }).catch(error => { reject(error); this.running--; this.runNext(); }); } } } const queue = new RequestQueue(3); export default { data() { return { productInfo: null, stockInfo: null, reviewCount: null }; }, async created() { const [productResponse, stockResponse, reviewResponse] = await Promise.all([ queue.enqueue(() => this.$http.get('/productInfo')), queue.enqueue(() => this.$http.get('/stockInfo')), queue.enqueue(() => this.$http.get('/reviewCount')) ]); this.productInfo = productResponse.data; this.stockInfo = stockResponse.data; this.reviewCount = reviewResponse.data; } };
- 使用