当前位置: 首页 > news >正文

vue2 面试题及详细答案150道(41 - 60)

前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。

前后端面试题-专栏总目录

在这里插入图片描述

文章目录

  • 一、本文面试题目录
      • 41. Vue中$nextTick的作用及使用场景
      • 42. Vuex中的getter有什么作用
      • 43. Vue中的过滤器(filter)有什么作用及使用方式
      • 44. 如何在Vue中使用SVG图标
      • 45. Vue项目中如何实现主题切换功能
      • 46. 简述Vue的虚拟DOM及Diff算法
      • 47. Vue中如何实现路由跳转及参数传递
      • 48. Vue项目中如何使用ECharts绘制图表
      • 49. Vue中mixin的优缺点
      • 50. Vue中如何监听对象或数组的变化
      • 51. Vue项目中如何实现文件上传功能
      • 52. Vue中如何实现组件的递归调用
      • 53. Vuex中的module是什么?如何使用
      • 54. Vue中如何实现页面刷新不丢失状态
      • 55. 简述Vue的混入(mixin)和Vuex的区别
      • 56. Vue中如何实现滚动到页面顶部或指定位置
      • 57. Vue项目中如何配置环境变量
      • 58. Vue中如何实现禁止浏览器回退
      • 59. Vue中如何实现图片的预览和裁剪功能
      • 60. 简述Vue2和Vue3的主要区别
  • 二、150道面试题目录列表

一、本文面试题目录

41. Vue中$nextTick的作用及使用场景

$nextTick是Vue提供的一个异步方法,其作用是在DOM更新完成后执行回调函数。因为Vue的DOM更新是异步的,当数据发生变化时,Vue不会立即更新DOM,而是将更新操作放入队列中,等同一事件循环中的所有数据变化完成后,再统一进行DOM更新。

使用场景包括:在修改数据后,需要立即操作更新后的DOM(如获取元素尺寸、位置等);在使用v-if/v-for等指令动态渲染元素后,需要对新生成的DOM进行操作。例如:

this.msg = '新内容';
this.$nextTick(() => {// 此时DOM已更新,可以获取到更新后的元素console.log(document.getElementById('content').innerText); // 输出'新内容'
});

42. Vuex中的getter有什么作用

getter相当于Vuex中的计算属性,它可以对store中的state进行加工处理,形成新的数据。其主要作用包括:

  • 缓存结果:getter的返回值会根据其依赖的state自动缓存,只有当依赖的state发生变化时,才会重新计算。
  • 简化组件代码:将对state的复杂计算逻辑抽离到getter中,避免在多个组件中重复编写相同逻辑,使组件代码更简洁。

示例:

const store = new Vuex.Store({state: {todos: [{ id: 1, text: '学习Vue', done: true },{ id: 2, text: '学习Vuex', done: false }]},getters: {doneTodos: state => {return state.todos.filter(todo => todo.done);}}
});

在组件中通过this.$store.getters.doneTodos获取过滤后的结果。

43. Vue中的过滤器(filter)有什么作用及使用方式

过滤器用于对文本进行格式化处理,可在模板插值和v-bind表达式中使用。

作用:对数据进行格式化,如日期格式化、字符串大小写转换等,不改变原始数据,只在显示时生效。

使用方式分为全局过滤器和局部过滤器:

  • 全局过滤器:通过Vue.filter()注册,可在所有组件中使用。
Vue.filter('uppercase', function(value) {if (!value) return '';return value.toUpperCase();
});
  • 局部过滤器:在组件的filters选项中定义,仅在当前组件中使用。
export default {filters: {lowercase: function(value) {if (!value) return '';return value.toLowerCase();}}
};

使用示例:

<p>{{ message | uppercase }}</p>
<img :src="imageUrl | formatUrl">

44. 如何在Vue中使用SVG图标

在Vue中使用SVG图标主要有以下几种方式:

  • 直接引入SVG文件:将SVG文件作为组件引入,在模板中直接使用。
<template><div><MySvgIcon /></div>
</template>
<script>
import MySvgIcon from './icons/my-icon.svg';
export default {components: { MySvgIcon }
};
</script>
  • 使用svg-sprite-loader:通过webpack配置svg-sprite-loader,将SVG图标合并为雪碧图,然后在模板中通过<use>标签引用。
    1. 安装loader:npm install svg-sprite-loader --save-dev
    2. 配置webpack(vue.config.js):
    module.exports = {chainWebpack: config => {config.module.rules.delete('svg');config.module.rule('svg').test(/\.svg$/).include.add(resolve('src/icons')).end().use('svg-sprite-loader').loader('svg-sprite-loader').options({ symbolId: 'icon-[name]' });}
    };
    
    1. 使用:
    <svg><use xlink:href="#icon-my-icon"></use>
    </svg>
    

45. Vue项目中如何实现主题切换功能

实现主题切换功能通常有以下步骤:

  1. 定义主题样式:通过CSS变量定义不同主题的样式,如在全局样式中定义:
:root {--primary-color: #42b983; /* 默认主题主色 */--bg-color: #ffffff; /* 默认主题背景色 */
}
.dark-theme {--primary-color: #35495e; /* 深色主题主色 */--bg-color: #1a1a1a; /* 深色主题背景色 */
}
  1. 在组件中使用CSS变量
.button {background-color: var(--primary-color);color: var(--text-color);
}
  1. 切换主题类名:在Vue实例中通过控制body或根元素的类名来切换主题:
export default {data() {return {isDarkTheme: false};},methods: {toggleTheme() {this.isDarkTheme = !this.isDarkTheme;if (this.isDarkTheme) {document.documentElement.classList.add('dark-theme');} else {document.documentElement.classList.remove('dark-theme');}// 可选:将主题偏好存储到localStoragelocalStorage.setItem('theme', this.isDarkTheme ? 'dark' : 'light');}},mounted() {// 初始化时读取本地存储的主题偏好const theme = localStorage.getItem('theme');if (theme === 'dark') {this.toggleTheme();}}
};

46. 简述Vue的虚拟DOM及Diff算法

虚拟DOM:是一个用JavaScript对象描述真实DOM结构的轻量级对象,它包含了标签名、属性、子节点等信息。虚拟DOM的存在避免了频繁操作真实DOM带来的性能开销,因为操作JavaScript对象比操作DOM更高效。

Diff算法:是Vue用于比较新旧虚拟DOM差异的算法,其核心思想是:

  • 同级比较:只比较同一层级的节点,不跨层级比较。
  • key的作用:通过key标识节点的唯一性,当节点顺序变化时,可复用已有节点,减少DOM操作。
  • 标签名比对:如果标签名不同,直接销毁旧节点并创建新节点。
  • 属性比对:如果标签名相同,则比较节点属性,只更新变化的属性。
  • 列表比对:对于列表节点,通过key找到可复用的节点,进行移动、新增或删除操作。

Diff算法的最终目的是计算出新旧虚拟DOM的差异,然后只将这些差异更新到真实DOM上,从而提高页面渲染性能。

47. Vue中如何实现路由跳转及参数传递

路由跳转方式

  • 声明式导航:使用<router-link>组件,to属性指定跳转路径。
<router-link to="/home">首页</router-link>
<router-link :to="{ path: '/user', query: { id: 1 } }">用户页</router-link>
  • 编程式导航:使用$router.push()方法。
// 字符串路径
this.$router.push('/home');
// 对象形式
this.$router.push({ path: '/user', params: { id: 1 } });

参数传递方式

  • query参数:类似于URL中的查询字符串,会显示在URL上,刷新页面参数不丢失。
    传递:this.$router.push({ path: '/user', query: { name: '张三' } })
    接收:this.$route.query.name
  • params参数:参数不会显示在URL上,需要在路由配置中定义占位符,刷新页面参数会丢失(若要保留需配合路由模式为history且服务端配置)。
    路由配置:{ path: '/user/:id', component: User }
    传递:this.$router.push({ name: 'User', params: { id: 1 } })(注意使用name跳转)
    接收:this.$route.params.id

48. Vue项目中如何使用ECharts绘制图表

在Vue项目中使用ECharts的步骤如下:

  1. 安装EChartsnpm install echarts --save
  2. 在组件中引入并使用
<template><div class="chart-container" ref="chart"></div>
</template>
<script>
import echarts from 'echarts';
export default {mounted() {// 初始化图表实例this.chart = echarts.init(this.$refs.chart);// 配置图表选项const option = {title: { text: '示例图表' },xAxis: { type: 'category', data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'] },yAxis: { type: 'value' },series: [{ data: [120, 200, 150, 80, 70], type: 'bar' }]};// 设置图表选项this.chart.setOption(option);// 监听窗口大小变化,重绘图表window.addEventListener('resize', this.handleResize);},methods: {handleResize() {this.chart.resize();}},beforeDestroy() {// 销毁图表实例,移除事件监听this.chart.dispose();window.removeEventListener('resize', this.handleResize);}
};
</script>
<style>
.chart-container {width: 100%;height: 400px;
}
</style>

49. Vue中mixin的优缺点

优点

  • 代码复用:可以将多个组件共用的逻辑(如数据、方法、生命周期钩子等)抽离到mixin中,减少代码冗余。
  • 灵活性:多个mixin可以被同一个组件引入,实现逻辑的组合。

缺点

  • 命名冲突:当组件和mixin或多个mixin之间存在同名的属性、方法或钩子函数时,会产生命名冲突,Vue的处理规则可能导致预期之外的结果(如数据对象浅合并,方法和钩子函数同名时mixin的会被组件的覆盖,钩子函数会被合并执行)。
  • 逻辑来源不清晰:组件中使用了多个mixin后,难以追踪某个功能或数据的具体来源,增加了代码的维护难度。
  • 耦合性高:mixin和组件之间可能存在隐式依赖,修改mixin可能会影响多个使用它的组件,不利于代码的模块化和独立性。

50. Vue中如何监听对象或数组的变化

由于JavaScript的限制,Vue不能直接检测对象属性的添加或删除,以及数组的某些变异方法(如length修改、通过索引直接修改元素)。但可以通过以下方式实现监听:

对象监听

  • 初始化时声明属性:在data中预先声明对象的属性,Vue会将其转为响应式。
  • 使用Vue.set():添加新属性时,使用Vue.set(object, propertyName, value)this.$set(object, propertyName, value)
this.$set(this.user, 'age', 20); // 给user对象添加age属性并使其响应式
  • 替换对象:将原对象替换为一个新的包含新增属性的对象。
this.user = { ...this.user, age: 20 };

数组监听

  • 使用数组变异方法:Vue对数组的push()pop()shift()unshift()splice()sort()reverse()方法进行了封装,调用这些方法会触发视图更新。
  • 使用Vue.set():通过索引修改数组元素时,使用Vue.set(array, index, value)this.$set(array, index, value)
this.$set(this.list, 0, '新值'); // 修改list数组索引为0的元素
  • 替换数组:将原数组替换为一个新的数组。
this.list = this.list.map(item => item + 1);

No.大剑师精品GIS教程推荐
0地图渲染基础- 【WebGL 教程】 - 【Canvas 教程】 - 【SVG 教程】
1Openlayers 【入门教程】 - 【源代码+示例 300+】
2Leaflet 【入门教程】 - 【源代码+图文示例 150+】
3MapboxGL【入门教程】 - 【源代码+图文示例150+】
4Cesium 【入门教程】 - 【源代码+综合教程 200+】
5threejs【中文API】 - 【源代码+图文示例200+】

51. Vue项目中如何实现文件上传功能

Vue项目中实现文件上传的基本步骤如下:

  1. 模板部分:使用<input type="file">元素获取文件,通过@change事件监听文件选择。
<template><div><input type="file" @change="handleFileChange" accept="image/*"><button @click="uploadFile">上传文件</button></div>
</template>
  1. 脚本部分
export default {data() {return {file: null};},methods: {handleFileChange(e) {this.file = e.target.files[0]; // 获取选择的文件},uploadFile() {if (!this.file) return;const formData = new FormData();formData.append('file', this.file); // 将文件添加到FormData// 发送请求this.$axios.post('/api/upload', formData, {headers: {'Content-Type': 'multipart/form-data' // 设置正确的Content-Type}}).then(response => {console.log('上传成功', response.data);}).catch(error => {console.error('上传失败', error);});}}
};
  1. 可选:实现多文件上传可将inputmultiple属性设为true,并处理files数组。

52. Vue中如何实现组件的递归调用

组件递归调用即组件自身调用自身,常用于实现树形结构、菜单等功能,实现方式如下:

  1. 定义组件:在组件中通过name选项指定组件名,然后在模板中使用该组件名进行递归调用。
<template><div class="tree-node"><div>{{ node.label }}</div><div v-if="node.children && node.children.length"><!-- 递归调用自身 --><tree-node v-for="(child, index) in node.children" :key="index" :node="child"></tree-node></div></div>
</template>
<script>
export default {name: 'TreeNode', // 必须指定组件名,用于递归调用props: {node: {type: Object,required: true}}
};
</script>
  1. 使用组件
<template><div><tree-node :node="treeData"></tree-node></div>
</template>
<script>
import TreeNode from './TreeNode.vue';
export default {components: { TreeNode },data() {return {treeData: {label: '根节点',children: [{label: '子节点1',children: [{ label: '孙节点1-1' }]},{ label: '子节点2' }]}};}
};
</script>

53. Vuex中的module是什么?如何使用

当Vuex的store变得庞大时,可使用module将store分割成多个模块,每个模块拥有自己的stategettermutationaction,甚至可以嵌套子模块。

使用方式

  1. 定义模块
// moduleA.js
export default {state: () => ({ count: 0 }),mutations: {increment(state) {state.count++;}},getters: {doubleCount(state) {return state.count * 2;}},actions: {incrementAsync({ commit }) {setTimeout(() => {commit('increment');}, 1000);}}
};
  1. 注册模块
import Vue from 'vue';
import Vuex from 'vuex';
import moduleA from './moduleA';Vue.use(Vuex);const store = new Vuex.Store({modules: {a: moduleA // 将模块A注册到store,命名为a}
});
  1. 访问模块内容
  • state:this.$store.state.a.count
  • getter:this.$store.getters.doubleCount(若模块内getter依赖全局state,可通过第二个参数获取)
  • mutation:this.$store.commit('increment')(默认模块内mutation是全局的,可通过namespaced: true开启命名空间)
  • action:this.$store.dispatch('incrementAsync')

命名空间:为避免模块间命名冲突,可在模块中设置namespaced: true,此时访问模块内的mutation、action、getter需加上模块名:

// moduleA中添加 namespaced: true
// 调用mutation
this.$store.commit('a/increment');
// 调用action
this.$store.dispatch('a/incrementAsync');
// 访问getter
this.$store.getters['a/doubleCount'];

54. Vue中如何实现页面刷新不丢失状态

实现页面刷新不丢失状态的常用方法有:

  • localStorage/sessionStorage:将需要持久化的状态存储在localStorage(永久存储)或sessionStorage(会话期间存储)中,在页面加载时读取并恢复状态。
// 存储
localStorage.setItem('userInfo', JSON.stringify(this.userInfo));
// 读取
mounted() {const userInfo = localStorage.getItem('userInfo');if (userInfo) {this.userInfo = JSON.parse(userInfo);}
}
  • Vuex持久化:使用vuex-persistedstate插件,自动将Vuex的state存储到localStorage等位置,具体配置见第21题。
  • Cookie:将少量关键信息存储在Cookie中,Cookie会随请求发送到服务器,也可在客户端读取,适合存储用户认证信息等。

55. 简述Vue的混入(mixin)和Vuex的区别

mixin

  • 用于组件间共享可复用的逻辑(数据、方法、生命周期等)。
  • 每个组件引入mixin后,mixin中的数据和方法会被合并到组件中,组件可以直接使用。
  • 数据是组件内部的,不同组件的mixin数据相互独立,修改不会相互影响。
  • 主要解决组件间逻辑复用问题,但存在命名冲突、逻辑来源不清晰等问题。

Vuex

  • 用于管理应用级别的共享状态,是一个集中式状态管理库。
  • 状态存储在全局的store中,所有组件都可以访问和修改(通过规定的方式)。
  • 数据是全局共享的,任何组件对状态的修改都会反映到所有使用该状态的组件中。
  • 主要解决跨组件、跨层级的数据共享和状态管理问题,遵循单向数据流,状态修改可追踪。

两者的核心区别在于:mixin用于组件级别的逻辑复用,数据是组件私有;Vuex用于应用级别的状态共享,数据是全局共享的。

56. Vue中如何实现滚动到页面顶部或指定位置

滚动到页面顶部

  • 使用window.scrollTo()方法:
// 滚动到顶部,behavior: 'smooth'实现平滑滚动
window.scrollTo({ top: 0, behavior: 'smooth' });
  • 在Vue中可通过按钮点击事件触发:
<button @click="scrollToTop">回到顶部</button>
methods: {scrollToTop() {window.scrollTo({ top: 0, behavior: 'smooth' });}
}

滚动到指定位置

  • 通过元素的scrollIntoView()方法:
<div ref="target">目标位置</div>
<button @click="scrollToTarget">滚动到目标</button>
methods: {scrollToTarget() {this.$refs.target.scrollIntoView({ behavior: 'smooth' });}
}
  • 使用window.scrollTo()指定滚动距离:
// 滚动到距离顶部500px的位置
window.scrollTo({ top: 500, behavior: 'smooth' });

57. Vue项目中如何配置环境变量

Vue项目中配置环境变量可通过以下步骤:

  1. 创建环境变量文件:在项目根目录下创建不同环境的配置文件:
    • .env:全局默认配置,所有环境都会加载。
    • .env.development:开发环境配置(npm run serve时加载)。
    • .env.production:生产环境配置(npm run build时加载)。
    • .env.test:测试环境配置(可自定义脚本加载)。
  2. 定义环境变量:文件中变量以VUE_APP_为前缀,例如:
# .env.development
VUE_APP_API_URL = 'http://dev.api.example.com'
VUE_APP_ENV = 'development'
  1. 在项目中使用:通过process.env访问环境变量。
console.log(process.env.VUE_APP_API_URL); // 输出http://dev.api.example.com
  1. 配置启动脚本(package.json):
"scripts": {"serve": "vue-cli-service serve","build": "vue-cli-service build","build:test": "vue-cli-service build --mode test" // 加载.env.test
}

58. Vue中如何实现禁止浏览器回退

实现禁止浏览器回退可通过监听popstate事件并阻止其默认行为,具体如下:

mounted() {// 监听浏览器历史记录变化window.addEventListener('popstate', this.handlePopState);// 推入一个空的历史记录,防止初始状态下回退到上一页history.pushState(null, null, document.URL);
},
methods: {handlePopState() {// 当用户点击回退时,再推入一个历史记录,抵消回退操作history.pushState(null, null, document.URL);// 可选:提示用户不能回退alert('禁止回退');}
},
beforeDestroy() {// 移除事件监听,避免影响其他页面window.removeEventListener('popstate', this.handlePopState);
}

注意:这种方法会修改浏览器的历史记录,可能影响用户体验,需谨慎使用,通常用于支付页、表单提交页等不希望用户回退的场景。

59. Vue中如何实现图片的预览和裁剪功能

图片预览:可通过FileReader读取本地图片文件并显示:

<input type="file" @change="previewImage" accept="image/*">
<img :src="imageUrl" v-if="imageUrl" alt="预览图">
data() {return {imageUrl: ''};
},
methods: {previewImage(e) {const file = e.target.files[0];if (!file) return;const reader = new FileReader();reader.onload = (event) => {this.imageUrl = event.target.result; // 得到图片的base64编码,用于预览};reader.readAsDataURL(file);}
}

图片裁剪:通常使用成熟的插件如vue-cropper

  1. 安装:npm install vue-cropper --save
  2. 使用:
<template><div><input type="file" @change="selectImage" accept="image/*"><vue-cropperv-if="imageUrl"ref="cropper":img="imageUrl":info="true":outputSize="0.8":outputType="'jpeg'"></vue-cropper><button @click="getCroppedImage">裁剪图片</button><img :src="croppedImage" v-if="croppedImage" alt="裁剪后"></div>
</template>
<script>
import { VueCropper } from 'vue-cropper';
export default {components: { VueCropper },data() {return {imageUrl: '',croppedImage: ''};},methods: {selectImage(e) {// 同上,获取imageUrl},getCroppedImage() {// 获取裁剪后的图片this.$refs.cropper.getCropBlob(blob => {const reader = new FileReader();reader.onload = (event) => {this.croppedImage = event.target.result;// 可将blob上传到服务器};reader.readAsDataURL(blob);});}}
};
</script>

60. 简述Vue2和Vue3的主要区别

响应式系统

  • Vue2:使用Object.defineProperty()劫持对象的getter和setter,无法直接监听对象属性的添加/删除和数组索引修改。
  • Vue3:使用Proxy代理对象,能原生支持监听对象属性的添加/删除、数组索引修改,以及Map、Set等数据结构。

组合式API vs 选项式API

  • Vue2:主要使用选项式API(data、methods、computed等选项)组织代码,逻辑复杂时容易出现“代码碎片化”。
  • Vue3:推出组合式API(setup、ref、reactive、computed等),可将相关逻辑组织在一起,提高代码的可维护性和复用性,同时保留选项式API供选择。

模板语法

  • Vue3支持多根节点模板,Vue2模板必须有且仅有一个根节点。
  • Vue3新增了v-memo指令,用于缓存模板片段,优化性能。

性能优化

  • Vue3的Diff算法进行了优化,对静态节点进行标记,减少比较次数。
  • Vue3的打包体积更小,通过tree-shaking移除未使用的代码。

其他

  • Vue3支持TypeScript,类型推断更友好。
  • Vue3的生命周期钩子有所变化,如beforeCreatecreatedsetup替代,mounted对应onMounted等(组合式API中)。
  • Vue3的全局API改为使用createApp创建应用实例,如Vue.createApp(App).mount('#app'),替代Vue2的new Vue({ el: '#app' })

二、150道面试题目录列表

文章序号vue2面试题150道
1vue2 面试题及详细答案(01 - 20)
2vue2 面试题及详细答案(21 - 40)
3vue2 面试题及详细答案(41 - 60)
4vue2 面试题及详细答案(61 - 70)
5vue2 面试题及详细答案(71 - 80)
6vue2 面试题及详细答案(81 - 90)
7vue2 面试题及详细答案(91 - 100)
8vue2 面试题及详细答案(101 - 120)
9vue2 面试题及详细答案(121 - 130)
10vue2 面试题及详细答案(131 - 140)
11vue2 面试题及详细答案(141 - 150)
http://www.dtcms.com/a/286321.html

相关文章:

  • Node.js链接MySql
  • Vue常见指令
  • Java大厂面试实录:从Spring Boot到AI微服务架构的深度解析
  • 深度学习零基础入门(3)-图像与神经网络
  • UE5 一些关于过场动画sequencer,轨道track的一些Python操作
  • 力扣347:前K个高频元素
  • 科技照亮童心|激光院与跳伞塔社区开展公益活动
  • Day24| 93.复原IP地址、78.子集、90.子集II
  • NIO简单介绍和运用
  • MySQL计数函数count原理分析
  • 深入理解Linux文件I/O:系统调用与标志位应用
  • 区块链加密技术全景解析
  • 高效VLP蛋白表达|病毒样颗粒生产|疫苗研发平台
  • 【无标题】标准模型粒子行为与11维拓扑量子色动力学模型严格对应的全面论述
  • 文献分享0719
  • MyBatis:配置文件完成增删改查_添加
  • 智慧后厨检测算法构建智能厨房防护网
  • 零基础入门:用按键精灵实现视频自动操作(附完整脚本)
  • C语言:数组
  • MySQL的关键日志
  • 洛谷 P1395 会议
  • Logback 配置的利器:深入理解<property>与<variable>
  • 教育行业网络升级最佳实践:SD-WAN、传统方案与混合方案对比分析
  • Android sdk 升级 34到35
  • SpringBoot中解决SpringApplication入口和其他Bean不在同属目录下的问题。
  • 暑期自学嵌入式——Day05补充(C语言阶段)
  • STM32+w5500+TcpClient学习笔记
  • 前端基础之《Vue(23)—跨域问题》
  • Effective Modern C++ 条款14:如果函数不抛出异常请使用noexcept
  • 如何将本地Git仓库推送到远程仓库的一个文件中并保留Commit记录