《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。
文章目录
- 一、本文面试题目录
-
-
- 101. Vue2中如何实现图片懒加载?
- 102. Vue2中如何处理大数据列表渲染性能问题?
- 103. Vue2中如何实现暗黑模式切换?
- 104. Vue2中如何实现组件的过渡动画?
- 105. Vue2中如何实现动态主题切换?
- 106. Vue2中如何实现路由权限控制?
- 107. Vue2中如何实现表单数据的双向绑定?
- 108. Vue2中如何实现插件?
- 109. Vue2中如何实现事件总线(Event Bus)?
- 110. Vue2中如何实现路由导航动画?
- 111. Vue2中如何实现自定义过滤器?
- 112. Vue2中如何实现自定义混入(Mixins)?
- 113. Vue2中如何实现无限级分类组件?
- 114. Vue2中如何实现拖拽功能?
- 115. Vue2中如何实现文件上传?
- 116. Vue2中如何实现图片预览?
- 117. Vue2中如何实现跨组件通信?
- 118. Vue2中如何实现组件的按需加载?
- 119. Vue2中如何实现状态管理?
- 120. Vue2中如何实现服务注入?
-
- 二、150道面试题目录列表
一、本文面试题目录
101. Vue2中如何实现图片懒加载?
- 答案:Vue2中实现图片懒加载有以下几种方式:
- 使用第三方插件:如
vue-lazyload
,使用方式如下:
- 使用第三方插件:如
import Vue from 'vue';
import App from './App.vue';
import VueLazyload from 'vue-lazyload';
Vue.use(VueLazyload, {
loading: 'loading.gif', // 加载中显示的图片
error: 'error.png', // 加载失败显示的图片
});
new Vue({
render: h => h(App),
}).$mount('#app');
在模板中使用:
<img v-lazy="imageUrl" alt="图片">
- **自定义指令**:通过监听图片元素的位置和视口的关系来实现,例如:
Vue.directive('lazy', {
inserted: function (el) {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
const img = new Image();
img.src = el.dataset.src;
img.onload = () => {
el.src = el.dataset.src;
};
observer.unobserve(el);
}
});
observer.observe(el);
},
});
在模板中使用:
<img v-lazy data-src="imageUrl" alt="图片">
102. Vue2中如何处理大数据列表渲染性能问题?
- 答案:处理Vue2中大数据列表渲染性能问题的方法有:
- 虚拟列表:只渲染可视区域的列表项,不可见区域的列表项不渲染,当滚动时动态更新渲染的列表项。可以使用第三方库如
vue-virtual-scroller
。 - 分批渲染:将大数据分成多个小批次进行渲染,避免一次性渲染大量数据导致页面卡顿。例如:
- 虚拟列表:只渲染可视区域的列表项,不可见区域的列表项不渲染,当滚动时动态更新渲染的列表项。可以使用第三方库如
export default {
data() {
return {
originalList: [], // 原始数据
displayList: [], // 当前显示的数据
batchSize: 20, // 每批渲染的数量
currentBatch: 0, // 当前批次
};
},
mounted() {
this.loadMore();
},
methods: {
loadMore() {
const start = this.currentBatch * this.batchSize;
const end = start + this.batchSize;
this.displayList = [...this.displayList, ...this.originalList.slice(start, end)];
this.currentBatch++;
},
},
};
- **对象冻结**:对于不需要响应式的数据,可以使用`Object.freeze()`冻结对象,减少Vue的响应式开销。
103. Vue2中如何实现暗黑模式切换?
- 答案:Vue2中实现暗黑模式切换有以下几种方式:
- CSS变量+Vuex:在根元素定义CSS变量,通过Vuex管理主题状态,切换主题时修改CSS变量的值。例如:
:root {
--bg-color: #ffffff;
--text-color: #000000;
}
.dark-mode {
--bg-color: #1a1a1a;
--text-color: #ffffff;
}
// store.js
export default new Vuex.Store({
state: {
darkMode: false,
},
mutations: {
toggleDarkMode(state) {
state.darkMode = !state.darkMode;
},
},
});
<template>
<div :class="{ 'dark-mode': $store.state.darkMode }">
<button @click="$store.commit('toggleDarkMode')">切换主题</button>
</div>
</template>
- **使用Tailwind CSS**:Tailwind CSS v3内置了暗黑模式支持,可以通过`dark:`前缀来定义暗黑模式下的样式。
104. Vue2中如何实现组件的过渡动画?
- 答案:Vue2中实现组件的过渡动画有以下几种方式:
- 使用
<transition>
组件:包裹需要过渡的元素或组件,例如:
- 使用
<transition name="fade">
<div v-if="show">Hello World</div>
</transition>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
- **使用`<transition-group>`组件**:用于列表过渡,例如:
<transition-group name="list" tag="ul">
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</transition-group>
.list-enter-active, .list-leave-active {
transition: all 0.5s;
}
.list-enter, .list-leave-to {
opacity: 0;
transform: translateX(30px);
}
- **自定义过渡类名**:可以通过`enter-class`、`leave-class`等属性来自定义过渡类名。
105. Vue2中如何实现动态主题切换?
- 答案:Vue2中实现动态主题切换有以下几种方式:
- CSS变量:通过修改根元素的CSS变量来实现主题切换,如前面暗黑模式的例子。
- 引入不同的CSS文件:根据主题切换不同的CSS文件,例如:
methods: {
switchTheme(theme) {
const themeLink = document.getElementById('theme-link');
if (themeLink) {
themeLink.href = `themes/${theme}.css`;
} else {
const link = document.createElement('link');
link.id = 'theme-link';
link.rel = 'stylesheet';
link.href = `themes/${theme}.css`;
document.head.appendChild(link);
}
},
}
- **使用第三方库**:如`vuetify`、`element-ui`等UI库提供了主题定制功能。
106. Vue2中如何实现路由权限控制?
- 答案:Vue2中实现路由权限控制通常有以下几种方式:
- 全局前置守卫:在路由配置中设置
meta
字段,然后在全局前置守卫中检查用户权限,例如:
- 全局前置守卫:在路由配置中设置
router.beforeEach((to, from, next) => {
const userRole = localStorage.getItem('userRole');
if (to.meta.requiresAuth) {
if (!userRole) {
next('/login');
} else if (to.meta.roles && !to.meta.roles.includes(userRole)) {
next('/forbidden');
} else {
next();
}
} else {
next();
}
});
路由配置:
{
path: '/admin',
component: Admin,
meta: {
requiresAuth: true,
roles: ['admin'],
},
}
- **组件内守卫**:在组件内使用`beforeRouteEnter`等守卫进行权限控制。
- **自定义指令**:创建一个自定义指令来控制DOM元素的显示与隐藏。
107. Vue2中如何实现表单数据的双向绑定?
- 答案:Vue2中实现表单数据的双向绑定主要使用
v-model
指令,它是一个语法糖,实际上是:value
和@input
的组合。例如:
<input v-model="message" type="text">
等价于:
<input :value="message" @input="message = $event.target.value" type="text">
对于不同的表单元素,v-model
的行为会有所不同:
- 文本框:绑定
value
属性和input
事件。 - 复选框:绑定
checked
属性和change
事件。 - 单选框:绑定
value
属性和change
事件。 - 下拉框:绑定
value
属性和change
事件。
108. Vue2中如何实现插件?
- 答案:Vue2中实现插件有以下几种方式:
- 对象形式:创建一个包含
install
方法的对象,例如:
- 对象形式:创建一个包含
const MyPlugin = {
install(Vue, options) {
// 添加全局方法或属性
Vue.myGlobalMethod = function () {
// 逻辑...
};
// 添加全局指令
Vue.directive('my-directive', {
bind(el, binding, vnode) {
// 逻辑...
},
});
// 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
};
},
};
// 使用插件
Vue.use(MyPlugin);
- **类形式**:创建一个类,然后在类中定义`install`方法。
109. Vue2中如何实现事件总线(Event Bus)?
- 答案:Vue2中实现事件总线有以下几种方式:
- 全局事件总线:创建一个全局的Vue实例作为事件总线,例如:
// event-bus.js
import Vue from 'vue';
export const eventBus = new Vue();
在组件中使用:
// 发送事件
import { eventBus } from './event-bus';
eventBus.$emit('message', 'Hello from component A');
// 接收事件
import { eventBus } from './event-bus';
eventBus.$on('message', (msg) => {
console.log(msg);
});
- **Vuex**:对于更复杂的状态管理,可以使用Vuex来替代事件总线。
110. Vue2中如何实现路由导航动画?
- 答案:Vue2中实现路由导航动画有以下几种方式:
- 使用
<transition>
包裹路由出口:例如:
- 使用
<transition name="fade">
<router-view></router-view>
</transition>
.fade-enter-active, .fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to {
opacity: 0;
}
- **根据路由方向设置不同的动画**:通过监听路由变化,设置不同的动画类名,例如:
<transition :name="transitionName">
<router-view></router-view>
</transition>
export default {
data() {
return {
transitionName: 'fade',
};
},
watch: {
$route(to, from) {
// 根据路由变化设置不同的动画
if (to.path.includes('detail')) {
this.transitionName = 'slide-left';
} else {
this.transitionName = 'slide-right';
}
},
},
};
No. | 大剑师精品GIS教程推荐 |
---|---|
0 | 地图渲染基础- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】 |
1 | Openlayers 【入门教程】 - 【源代码+示例 300+】 |
2 | Leaflet 【入门教程】 - 【源代码+图文示例 150+】 |
3 | MapboxGL 【入门教程】 - 【源代码+图文示例150+】 |
4 | Cesium 【入门教程】 - 【源代码+综合教程 200+】 |
5 | threejs 【中文API】 - 【源代码+图文示例200+】 |
111. Vue2中如何实现自定义过滤器?
- 答案:Vue2中实现自定义过滤器有以下几种方式:
- 全局过滤器:在Vue实例创建前定义,例如:
Vue.filter('capitalize', function (value) {
if (!value) return '';
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
});
在模板中使用:
{{ message | capitalize }}
- **局部过滤器**:在组件内部定义,例如:
export default {
filters: {
capitalize(value) {
if (!value) return '';
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
},
},
};
112. Vue2中如何实现自定义混入(Mixins)?
- 答案:Vue2中实现自定义混入有以下几种方式:
- 全局混入:在Vue实例创建前定义,例如:
Vue.mixin({
created() {
console.log('全局混入的created钩子');
},
});
- **局部混入**:在组件内部使用,例如:
// mixin.js
export const myMixin = {
data() {
return {
mixinData: '这是混入的数据',
};
},
methods: {
mixinMethod() {
console.log('这是混入的方法');
},
},
};
// 在组件中使用
import { myMixin } from './mixin';
export default {
mixins: [myMixin],
};
113. Vue2中如何实现无限级分类组件?
- 答案:Vue2中实现无限级分类组件通常使用递归组件,例如:
<!-- CategoryItem.vue -->
<template>
<div>
<div>{{ item.name }}</div>
<div v-if="item.children && item.children.length > 0">
<CategoryItem v-for="child in item.children" :key="child.id" :item="child" />
</div>
</div>
</template>
<script>
export default {
name: 'CategoryItem',
props: {
item: {
type: Object,
required: true,
},
},
};
</script>
在父组件中使用:
<template>
<div>
<CategoryItem v-for="category in categories" :key="category.id" :item="category" />
</div>
</template>
<script>
import CategoryItem from './CategoryItem.vue';
export default {
components: {
CategoryItem,
},
data() {
return {
categories: [
{
id: 1,
name: '分类1',
children: [
{
id: 2,
name: '分类1-1',
children: [],
},
],
},
],
};
},
};
</script>
114. Vue2中如何实现拖拽功能?
- 答案:Vue2中实现拖拽功能有以下几种方式:
- 原生JavaScript:使用HTML5的Drag and Drop API,例如:
<div
draggable="true"
@dragstart="dragStart"
@dragend="dragEnd"
>
拖拽元素
</div>
methods: {
dragStart(e) {
e.dataTransfer.setData('text/plain', e.target.id);
},
dragEnd() {
// 拖拽结束处理
},
}
- **第三方库**:如`vuedraggable`,它是基于Sortable.js的Vue拖拽组件,使用方式如下:
<draggable v-model="list">
<div v-for="item in list" :key="item.id">{{ item.name }}</div>
</draggable>
import draggable from 'vuedraggable';
export default {
components: {
draggable,
},
data() {
return {
list: [
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
],
};
},
};
115. Vue2中如何实现文件上传?
- 答案:Vue2中实现文件上传有以下几种方式:
- 原生表单提交:使用
<input type="file">
和FormData对象,例如:
- 原生表单提交:使用
<template>
<div>
<input type="file" @change="handleFileUpload" />
<button @click="uploadFile">上传文件</button>
</div>
</template>
<script>
export default {
data() {
return {
selectedFile: null,
};
},
methods: {
handleFileUpload(event) {
this.selectedFile = event.target.files[0];
},
uploadFile() {
const formData = new FormData();
formData.append('file', this.selectedFile);
axios.post('/api/upload', formData)
.then(response => {
console.log('上传成功');
})
.catch(error => {
console.error('上传失败', error);
});
},
},
};
</script>
- **第三方库**:如`vue-upload-component`,提供了更丰富的上传功能。
116. Vue2中如何实现图片预览?
- 答案:Vue2中实现图片预览通常使用FileReader API,例如:
<template>
<div>
<input type="file" @change="previewImage" accept="image/*" />
<img v-if="previewUrl" :src="previewUrl" alt="预览图" />
</div>
</template>
<script>
export default {
data() {
return {
previewUrl: null,
};
},
methods: {
previewImage(event) {
const file = event.target.files[0];
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
this.previewUrl = e.target.result;
};
reader.readAsDataURL(file);
}
},
},
};
</script>
117. Vue2中如何实现跨组件通信?
- 答案:Vue2中实现跨组件通信有以下几种方式:
- 事件总线(Event Bus):创建一个全局的事件总线对象,组件之间通过它来发布和订阅事件。
- Vuex:用于管理应用的全局状态,适合复杂的大型应用。
- p a r e n t 、 parent、 parent、children、$refs:直接访问父组件、子组件或引用特定的组件实例。
- provide/inject:用于祖先组件向子孙组件传递数据,不需要逐级传递props。
- 自定义事件:通过$emit触发自定义事件,在父组件中监听。
118. Vue2中如何实现组件的按需加载?
- 答案:Vue2中实现组件的按需加载有以下几种方式:
- 异步组件:使用动态import语法,例如:
const AsyncComponent = () => import('./AsyncComponent.vue');
export default {
components: {
AsyncComponent,
},
};
- **路由懒加载**:在路由配置中使用动态import,例如:
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue'),
}
119. Vue2中如何实现状态管理?
- 答案:Vue2中实现状态管理有以下几种方式:
- Vuex:官方推荐的状态管理库,适合大型应用,管理应用的全局状态。
- localStorage/sessionStorage:将数据存储在浏览器的本地存储中,适合简单的数据持久化。
- event bus:用于组件间的简单通信,管理少量的共享状态。
- Vue.observable():创建一个响应式对象,适合小型应用或插件的状态管理。
120. Vue2中如何实现服务注入?
- 答案:Vue2中实现服务注入有以下几种方式:
- 全局注册:将服务注册为全局变量,例如:
// 定义服务
const myService = {
fetchData() {
return axios.get('/api/data');
},
};
// 在Vue实例中注入
Vue.prototype.$myService = myService;
在组件中使用:
this.$myService.fetchData().then(response => {
// 处理响应
});
- **provide/inject**:在祖先组件中提供服务,在子孙组件中注入,例如:
// 祖先组件
export default {
provide() {
return {
myService: this.$myService,
};
},
};
// 子孙组件
export default {
inject: ['myService'],
mounted() {
this.myService.fetchData().then(response => {
// 处理响应
});
},
};