vue2 面试题及详细答案150道(71 - 80)
《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。
文章目录
- 一、本文面试题目录
- 71. Vue中如何实现路由守卫
- 72. Vue中如何实现组件的懒加载
- 73. Vue中如何实现一个无限滚动列表
- 74. Vue中如何实现一个搜索框的防抖功能
- 75. Vue中如何实现一个表单验证功能
- 76. Vue中如何实现一个选项卡组件
- 77. Vue中如何实现一个进度条组件
- 78. Vue中如何实现一个拖拽排序功能
- 79. Vue中如何实现一个模态框组件
- 80. Vue中如何实现一个计时器组件
- 二、150道面试题目录列表
一、本文面试题目录
71. Vue中如何实现路由守卫
Vue中路由守卫用于控制导航的访问权限或在导航前后执行一些操作,分为全局守卫、路由独享守卫和组件内守卫。
全局守卫:
// main.js
router.beforeEach((to, from, next) => {// 全局前置守卫,在路由切换前执行if (to.meta.requiresAuth &&!isAuthenticated()) {next('/login'); // 未登录时重定向到登录页} else {next(); // 放行}
});router.afterEach((to, from) => {// 全局后置钩子,在路由切换后执行document.title = to.meta.title || '默认标题';
});
路由独享守卫:
const routes = [{path: '/admin',component: Admin,beforeEnter: (to, from, next) => {// 路由独享守卫if (isAdmin()) {next();} else {next('/forbidden');}}}
];
组件内守卫:
export default {beforeRouteEnter(to, from, next) {// 在渲染该组件的对应路由被确认前调用// 不能访问this,因为组件实例还未被创建next(vm => {// 通过vm访问组件实例});},beforeRouteUpdate(to, from, next) {// 在当前路由改变,但是该组件被复用时调用// 可以访问this},beforeRouteLeave(to, from, next) {// 在导航离开渲染该组件的对应路由时调用// 常用于询问用户是否保存未保存的更改const answer = window.confirm('确定要离开吗?');if (answer) {next();} else {next(false);}}
};
72. Vue中如何实现组件的懒加载
Vue中实现组件的懒加载(异步组件)有以下几种方式:
1. 基本异步组件:
const AsyncComponent = () => import('./components/AsyncComponent.vue');export default {components: {AsyncComponent}
};
2. 路由懒加载:
const routes = [{path: '/about',name: 'About',// 路由懒加载component: () => import('./views/About.vue')}
];
3. 带加载状态的异步组件:
const AsyncComponent = () => ({// 需要加载的组件 (应该是一个 Promise)component: import('./components/AsyncComponent.vue'),// 异步组件加载时使用的组件loading: LoadingComponent,// 加载失败时使用的组件error: ErrorComponent,// 展示加载时组件的延时时间。默认值是 200 (毫秒)delay: 200,// 如果提供了超时时间且组件加载超时,将使用错误组件。默认值是:Infinitytimeout: 3000
});
4. 使用webpack的魔法注释:
const routes = [{path: '/home',component: () => import(/* webpackChunkName: "home" */ './views/Home.vue')}
];
通过魔法注释可以指定打包后的文件名,便于调试和维护。
73. Vue中如何实现一个无限滚动列表
实现无限滚动列表(下拉加载更多)通常结合Intersection Observer API或监听scroll事件来实现:
方法一:使用Intersection Observer API:
<template><div class="infinite - list"><div v - for="item in items" :key="item.id">{{ item.name }}</div><div ref="observerTarget" v - if="loading">加载中...</div></div>
</template>
<script>
export default {data() {return {items: [],page: 1,loading: false,observer: null};},mounted() {this.loadData();this.initObserver();},beforeDestroy() {if (this.observer) {this.observer.disconnect();}},methods: {async loadData() {this.loading = true;const newItems = await this.fetchItems(this.page);this.items = [...this.items,...newItems];this.page++;this.loading = false;},initObserver() {this.observer = new IntersectionObserver((entries) => {if (entries[0].isIntersecting &&!this.loading) {this.loadData();}},{ threshold: 0.1 });this.observer.observe(this.$refs.observerTarget);}}
};
</script>
方法二:监听scroll事件:
<template><div class="infinite - list" @scroll="handleScroll"><div v - for="item in items" :key="item.id">{{ item.name }}</div><div v - if="loading">加载中...</div></div>
</template>
<script>
export default {data() {return {items: [],page: 1,loading: false};},methods: {handleScroll() {const { scrollTop, scrollHeight, clientHeight } = this.$el;if (scrollTop + clientHeight >= scrollHeight - 100 &&!this.loading) {this.loadMore();}},async loadMore() {this.loading = true;const newItems = await this.fetchItems(this.page);this.items = [...this.items,...newItems];this.page++;this.loading = false;}}
};
</script>
74. Vue中如何实现一个搜索框的防抖功能
在Vue中实现搜索框的防抖功能可以通过以下步骤:
方法一:使用lodash的debounce函数:
<template><div><input v - model="searchText" @input="debouncedSearch" placeholder="搜索..."></div>
</template>
<script>
import debounce from 'lodash/debounce';export default {data() {return {searchText: '',results: []};},created() {// 创建防抖函数this.debouncedSearch = debounce(this.search, 300);},methods: {async search() {if (!this.searchText.trim()) {this.results = [];return;}// 执行搜索操作const response = await this.$axios.get('/api/search', {params: {q: this.searchText}});this.results = response.data;}}
};
</script>
方法二:手动实现防抖:
<template><div><input v - model="searchText" @input="handleInput" placeholder="搜索..."></div>
</template>
<script>
export default {data() {return {searchText: '',results: [],timer: null};},methods: {handleInput() {// 清除之前的定时器if (this.timer) {clearTimeout(this.timer);}// 设置新的定时器this.timer = setTimeout(() => {this.search();}, 300);},async search() {// 搜索逻辑同上}}
};
</script>
75. Vue中如何实现一个表单验证功能
Vue中实现表单验证可以通过以下几种方式:
方法一:手动验证:
<template><form @submit.prevent="submitForm"><div><label>用户名:</label><input v - model="username" @blur="validateUsername"><span v - if="errors.username">{{ errors.username }}</span></div><div><label>邮箱:</label><input v - model="email" @blur="validateEmail"><span v - if="errors.email">{{ errors.email }}</span></div><button type="submit">提交</button></form>
</template>
<script>
export default {data() {return {username: '',email: '',errors: {username: '',email: ''}};},methods: {validateUsername() {if (!this.username) {this.errors.username = '用户名不能为空';} else if (this.username.length < 3) {this.errors.username = '用户名长度不能少于3个字符';} else {this.errors.username = '';}},validateEmail() {const re = /^.+@.+$/;if (!this.email) {this.errors.email = '邮箱不能为空';} else if (!re.test(this.email)) {this.errors.email = '邮箱格式不正确';} else {this.errors.email = '';}},submitForm() {// 提交前再次验证所有字段this.validateUsername();this.validateEmail();// 检查是否有错误if (!this.errors.username &&!this.errors.email) {// 提交表单console.log('表单提交成功');} else {console.log('表单验证失败');}}}
};
</script>
方法二:使用vee - validate插件:
npm install vee - validate@3 --save
<template><form @submit.prevent="submitForm"><div><label>用户名:</label><input v - model="username" v - rules="required|min:3"><span>{{ errors.first('username') }}</span></div><div><label>邮箱:</label><input v - model="email" v - rules="required|email"><span>{{ errors.first('email') }}</span></div><button type="submit">提交</button></form>
</template>
<script>
import { ValidationProvider, ValidationObserver, extend } from 'vee - validate';
import { required, email, min } from 'vee - validate/dist/rules';// 扩展验证规则
extend('required', required);
extend('email', email);
extend('min', min);export default {components: {ValidationProvider,ValidationObserver},data() {return {username: '',email: ''};},methods: {async submitForm() {const isValid = await this.$refs.observer.validate();if (isValid) {console.log('表单提交成功');} else {console.log('表单验证失败');}}}
};
</script>
76. Vue中如何实现一个选项卡组件
实现一个选项卡组件可以按照以下步骤:
1. 创建选项卡组件:
<template><div class="tabs"><div class="tab - headers"><divv - for="(tab, index) in tabs":key="index":class="{ 'active': currentTab === index }"@click="switchTab(index)">{{ tab.title }}</div></div><div class="tab - content"><component :is="currentComponent"></component></div></div>
</template>
<script>
export default {props: {tabs: {type: Array,required: true}},data() {return {currentTab: 0};},computed: {currentComponent() {return this.tabs[this.currentTab].component;}},methods: {switchTab(index) {this.currentTab = index;this.$emit('tab - change', index);}}
};
</script>
<style scoped>
.tab - headers {display: flex;border - bottom: 1px solid #ccc;
}
.tab - headers > div {padding: 10px 15px;cursor: pointer;
}
.tab - headers > div.active {border - bottom: 2px solid #42b983;color: #42b983;
}
.tab - content {padding: 15px;
}
</style>
2. 使用选项卡组件:
<template><div><Tabs :tabs="myTabs" @tab - change="handleTabChange" /></div>
</template>
<script>
import Tabs from './Tabs.vue';
import Tab1 from './Tab1.vue';
import Tab2 from './Tab2.vue';
import Tab3 from './Tab3.vue';export default {components: { Tabs },data() {return {myTabs: [{ title: '选项卡1', component: Tab1 },{ title: '选项卡2', component: Tab2 },{ title: '选项卡3', component: Tab3 }]};},methods: {handleTabChange(index) {console.log('切换到选项卡:', index);}}
};
</script>
77. Vue中如何实现一个进度条组件
实现一个进度条组件可以按照以下步骤:
1. 创建进度条组件:
<template><div class="progress - bar"><div class="progress - track"><divclass="progress - fill":style="{ width: `${percentage}%` }":class="{ 'with - animation': animated }"></div></div><div v - if="showText" class="progress - text">{{ percentage }}%</div></div>
</template>
<script>
export default {props: {percentage: {type: Number,required: true,min: 0,max: 100},animated: {type: Boolean,default: false},showText: {type: Boolean,default: true}}
};
</script>
<style scoped>
.progress - bar {display: flex;align-items: center;
}
.progress - track {flex: 1;height: 20px;background - color: #f0f0f0;border - radius: 10px;overflow: hidden;
}
.progress - fill {height: 100%;background - color: #42b983;transition: width 0.3s ease - in - out;
}
.progress - text {margin - left: 10px;font - size: 14px;
}
</style>
2. 使用进度条组件:
<template><div><ProgressBar :percentage="50" /><ProgressBar :percentage="loadingProgress" animated showText /><button @click="startLoading">开始加载</button></div>
</template>
<script>
import ProgressBar from './ProgressBar.vue';export default {components: { ProgressBar },data() {return {loadingProgress: 0};},methods: {startLoading() {let progress = 0;const interval = setInterval(() => {progress += 5;this.loadingProgress = progress;if (progress >= 100) {clearInterval(interval);}}, 200);}}
};
</script>
78. Vue中如何实现一个拖拽排序功能
Vue中实现拖拽排序功能可以通过以下步骤:
方法一:使用Sortable.js:
npm install sortablejs --save
<template><div><ul ref="list"><li v - for="(item, index) in items" :key="item.id">{{ item.name }}</li></ul></div>
</template>
<script>
import Sortable from 'sortablejs';export default {data() {return {items: [{ id: 1, name: '项目1' },{ id: 2, name: '项目2' },{ id: 3, name: '项目3' }]};},mounted() {new Sortable(this.$refs.list, {animation: 150,onEnd: (evt) => {// 获取拖拽前后的索引const { oldIndex, newIndex } = evt;// 更新数组顺序const item = this.items.splice(oldIndex, 1)[0];this.items.splice(newIndex, 0, item);}});}
};
</script>
方法二:原生实现简单拖拽排序:
<template><div><ul><liv - for="(item, index) in items":key="item.id"draggable="true"@dragstart="handleDragStart(index)"@dragover.prevent@drop="handleDrop(index)">{{ item.name }}</li></ul></div>
</template>
<script>
export default {data() {return {items: [{ id: 1, name: '项目1' },{ id: 2, name: '项目2' },{ id: 3, name: '项目3' }],draggedIndex: null};},methods: {handleDragStart(index) {this.draggedIndex = index;},handleDrop(index) {if (this.draggedIndex!== null && this.draggedIndex!== index) {const item = this.items.splice(this.draggedIndex, 1)[0];this.items.splice(index, 0, item);this.draggedIndex = null;}}}
};
</script>
<style scoped>
li {cursor: move;padding: 10px;margin: 5px;border: 1px solid #ccc;list - style: none;
}
</style>
79. Vue中如何实现一个模态框组件
实现一个模态框组件可以按照以下步骤:
1. 创建模态框组件:
<template><div class="modal" v - if="visible"><div class="modal - overlay" @click="close"></div><div class="modal - content"><div class="modal - header"><h3>{{ title }}</h3><button @click="close">×</button></div><div class="modal - body"><slot></slot></div><div class="modal - footer"><button @click="close">取消</button><button @click="confirm">确定</button></div></div></div>
</template>
<script>
export default {props: {visible: {type: Boolean,default: false},title: {type: String,default: '模态框标题'}},methods: {close() {this.$emit('update:visible', false);this.$emit('cancel');},confirm() {this.$emit('update:visible', false);this.$emit('confirm');}}
};
</script>
<style scoped>
.modal {position: fixed;top: 0;left: 0;width: 100%;height: 100%;display: flex;justify - content: center;align - items: center;z - index: 1000;
}
.modal - overlay {position: absolute;top: 0;left: 0;width: 100%;height: 100%;background - color: rgba(0, 0, 0, 0.5);
}
.modal - content {position: relative;background - color: white;border - radius: 4px;box - shadow: 0 2px 10px rgba(0, 0, 0, 0.1);width: 500px;max - width: 90%;
}
.modal - header {padding: 15px;border - bottom: 1px solid #eee;display: flex;justify - content: space - between;align - items: center;
}
.modal - body {padding: 15px;
}
.modal - footer {padding: 15px;border - top: 1px solid #eee;text - align: right;
}
button {padding: 8px 16px;margin - left: 10px;
}
</style>
2. 使用模态框组件:
<template><div><button @click="showModal">打开模态框</button><Modal:visible="modalVisible"@update:visible="modalVisible = $event"@confirm="handleConfirm"@cancel="handleCancel"><p>这是模态框的内容</p></Modal></div>
</template>
<script>
import Modal from './Modal.vue';export default {components: { Modal },data() {return {modalVisible: false};},methods: {showModal() {this.modalVisible = true;},handleConfirm() {console.log('用户点击了确定');},handleCancel() {console.log('用户点击了取消');}}
};
</script>
80. Vue中如何实现一个计时器组件
实现一个计时器组件可以按照以下步骤:
1. 创建计时器组件:
<template><div class="timer"><div class="time">{{ formattedTime }}</div><div class="controls"><button @click="start">开始</button><button @click="pause">暂停</button><button @click="reset">重置</button></div></div>
</template>
<script>
export default {data() {return {startTime: 0,elapsedTime: 0,interval: null,isRunning: false};},computed: {formattedTime() {const seconds = Math.floor(this.elapsedTime / 1000);const minutes = Math.floor(seconds / 60);const remainingSeconds = seconds % 60;return `${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`;}},methods: {start() {if (!this.isRunning) {this.startTime = Date.now() - this.elapsedTime;this.interval = setInterval(() => {this.elapsedTime = Date.now() - this.startTime;}, 1000);this.isRunning = true;}},pause() {if (this.isRunning) {clearInterval(this.interval);this.isRunning = false;}},reset() {this.pause();this.elapsedTime = 0;}},beforeDestroy() {this.pause();}
};
</script>
<style scoped>
.time {font - size: 24px;margin - bottom: 10px;
}
.controls {display: flex;gap: 10px;
}
button {padding: 8px 16px;
}
</style>
2. 使用计时器组件:
<template><div><Timer /></div>
</template>
<script>
import Timer from './Timer.vue';export default {components: { Timer }
};
</script>
二、150道面试题目录列表
文章序号 | vue2面试题150道 |
---|---|
1 | vue2 面试题及详细答案(01 - 20) |
2 | vue2 面试题及详细答案(21 - 40) |
3 | vue2 面试题及详细答案(41 - 60) |
4 | vue2 面试题及详细答案(61 - 70) |
5 | vue2 面试题及详细答案(71 - 80) |
6 | vue2 面试题及详细答案(81 - 90) |
7 | vue2 面试题及详细答案(91 - 100) |
8 | vue2 面试题及详细答案(101 - 120) |
9 | vue2 面试题及详细答案(121 - 130) |
10 | vue2 面试题及详细答案(131 - 140) |
11 | vue2 面试题及详细答案(141 - 150) |