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

vue前端面试题——记录一次面试当中遇到的题(2)

1.vue2和vue3的区别
一、核心机制与响应式原理(最根本的区别)

Vue 2:使用 Object.defineProperty

  • 原理: 通过遍历对象的所有属性,并使用 Object.defineProperty 将它们转换为 getter/setter 来实现响应式。

  • 局限性:

    1. 无法检测属性的添加或删除: 必须使用 Vue.set 或 this.$set 来确保新属性是响应式的。

    2. 无法检测数组索引和长度的变化: 通过索引设置数组项 (arr[index] = newValue) 或修改数组长度 (arr.length = newLength) 不会被检测到。Vue 2通过重写数组的7个变更方法(如 pushpopsplice 等)来 hack 解决。

    3. 性能问题: 对于深层嵌套的对象,需要递归遍历所有属性,初始化性能较差。

Vue 3:使用 Proxy

  • 原理: 通过ES6的 Proxy 来代理整个对象,创建一个对象的“拦截层”。
  • 优势:
    • 支持更多数据结构: 原生支持 MapSetWeakMapWeakSet 等。

    • 性能提升: 只在 Proxy 层面进行拦截,无需递归初始化所有属性,只有在访问到嵌套对象时才会递归处理,延迟了计算,提升了初始化性能。

    • 更好的数组支持: 天然支持数组索引和长度的直接操作。

    • 全面拦截: 可以检测到所有属性的增、删、改、查,包括动态添加的属性,无需使用 Vue.set

二、组合式 API (Composition API) vs 选项式 API (Options API)

Vue 2:选项式 API

  • 组织方式: 将代码按照逻辑关注点(如数据、方法、计算属性、生命周期等)分散在不同的选项(datamethodscomputedmounted 等)中。

  • 缺点: 当一个组件的逻辑复杂时,同一功能的代码会被拆分到不同选项,导致组件难以阅读和维护。尤其是在使用 mixin 共享逻辑时,容易发生命名冲突和数据来源不清晰的问题。

Vue 3:组合式 API (主要新增,选项式 API 仍支持)

  • 组织方式: 允许你将与同一逻辑功能相关的代码(状态、方法、生命周期等)组织在一起。

  • 核心: setup 函数和一系列响应式API(如 refreactivecomputedwatch 等)。

  • 优势:

    1. 更好的逻辑复用与代码组织: 可以将相关的逻辑抽取到一个独立的“组合函数”(Composable)中,实现高度可复用的逻辑。

    2. 更灵活的代码组织: 代码按功能而非选项进行组织,使得复杂组件更易于理解和维护。

    3. 更好的 TypeScript 支持: 消除了 this 的类型推断问题,因为 setup 中几乎没有 this

三、生命周期变化

生命周期钩子被重新命名以更好地配合组合式 API。

  • beforeCreate -> 使用 setup()

  • created -> 使用 setup()

  • beforeMount -> onBeforeMount

  • mounted -> onMounted

  • beforeUpdate -> onBeforeUpdate

  • updated -> onUpdated

  • beforeDestroy -> onBeforeUnmount

  • destroyed -> onUnmounted

  • 新增: onErrorCaptured (捕获子孙组件的错误)

注意:Vue 3 中 beforeDestroy 和 destroyed 已被重命名为 onBeforeUnmount 和 onUnmounted,但旧名称在 Vue 3 中仍作为别名使用。

四、性能与打包体积优化
  • 更小的体积: Vue 3 通过 Tree-shaking 优化,使得很多不常用的 API(如 transitionv-model 指令等)可以被摇掉,最终打包体积比 Vue 2 小很多。

  • 虚拟 DOM 重写: 优化了虚拟 DOM 的 diff 算法,在编译时提供了更多的提示信息,减少了运行时比较的开销。

  • 编译器优化: 如静态节点提升(Hoist Static)、Patch Flags 等,减少了不必要的更新操作。

2.vue2和vue3 性能方面的区别

一、打包体积(Bundle Size)
  • Vue 2: 无论我们用到哪些功能,最终打包的整个 Vue 核心库都会被打进来。例如,即使用不到 transition 组件,它的代码也无法被移除。

  • Vue 3: 引入了 Tree-shaking(摇树优化)机制。Vue 3 的绝大多数全局 API 和内部组件(如 v-modeltransition 等)都设计为可以通过 ES Module 的 import 语法按需引入。

    • 原理: 打包工具(如 Webpack、Vite)在打包时会静态分析代码,只将项目中实际使用到的 API 和模块打包到最终产物中。

    • 结果: 对于一个只使用了 Vue 核心功能的项目,Vue 3 的打包体积可以比 Vue 2 小 40%+。项目依赖的功能越少,体积优化效果越明显。

二、编译时优化(Compiler Optimizations)

Vue 3 的模板编译器变得更“智能”,它会在编译模板时进行分析,并生成更优化的渲染函数代码。

  1. 静态节点提升(Hoist Static)

    • Vue 2: 在每次重新渲染时,无论元素是否是静态的(如 <div>Hello World</div>),都会创建新的 VNode 节点,并进行完整的 Diff 比较。

    • Vue 3: 编译器会识别出纯静态的节点和子树,并将其“提升”到渲染函数之外。

      • 结果: 这些静态节点只会在首次渲染时创建一次,后续更新时会直接复用,完全跳过 Diff 过程。这大大减少了 VNode 创建和比较的开销。

  2. Patch Flags(补丁标志)

    • Vue 2: 在对比两个 VNode 时,由于不知道具体是哪个部分会变化,因此需要递归地比较所有属性、子节点等,这是一项相对昂贵的操作。

    • Vue 3: 编译器会在动态节点上打上一个 PatchFlag 标记(一个数字),标识出这个节点需要更新的具体内容类型,例如 1 代表 文本 变化,2 代表 class 变化,4 代表 style 变化等。

      • 结果: 在运行时,Diff 算法可以直接根据这些标志进行定向更新。比如一个节点只有 class 会变,那么运行时只需要检查 class 而无需关心其他属性,极大地提升了 Diff 效率。

  3. 缓存事件处理函数(Cache Handler)

    • 问题: 在 Vue 2 中,内联的事件处理函数(如 @click="() => {...}")在每次父组件更新时都会被视作一个新的函数,导致子组件不必要的更新。

    • Vue 3: 编译器会自动缓存内联事件处理函数。除非事件依赖的响应式数据发生变化,否则处理函数会被缓存起来,避免子组件的无效重渲染

三、响应式系统(Reactive System)

这是性能提升最关键的一环,从 Object.defineProperty 切换到 Proxy

  • Vue 2 (Object.defineProperty):

    • 初始化性能: 在初始化时,需要递归地遍历数据对象的所有属性,并使用 Object.defineProperty 进行转换。对于深层嵌套的大对象,这个过程会比较慢。

    • 内存开销: 需要为每个对象的每个属性维护一个依赖关系列表(Dep),内存占用相对较高。

  • Vue 3 (Proxy):

    • 初始化性能: Proxy 是代理整个对象,无需递归遍历所有属性。它只在属性被访问时才会递归将其转换为响应式,这是一种“惰性”处理,初始化速度更快。

    • 内存开销: Proxy 不需要为每个属性创建 Dep,它只在getter中动态地追踪依赖,内存效率更高。

    • 组件更新粒度: Vue 3 的响应式系统与组件的渲染关联更精确,可以减少不必要的组件更新

四、虚拟 DOM 与 Diff 算法

虽然 Vue 3 依然使用虚拟 DOM,但其内部的 Diff 算法经过了彻底的重写。

  • Vue 2: 采用的是一个全面的、递归的 Diff 算法。当组件更新时,会从根节点开始,递归地比较新旧两棵 VNode 树。

  • Vue 3:

    • 得益于编译时的 Patch Flags,运行时可以跳过大量的无意义比较。

    • 实现了更高效的更新类型推断,例如,在对比子节点列表时,采用了更快速的双端比较算法,并优先处理常见的更新模式(如头尾节点的增删)

3.兼容性的问题之前遇到过吗?是怎么解决的?

1. 浏览器兼容性

这是最常见的一类,尤其是需要支持旧版浏览器(如 IE)时。

  • 问题场景:

    • 使用了 ES6+ 新特性(如 PromiseArray.prototype.includes, 箭头函数, const/let)。

    • 使用了现代浏览器才支持的 Web API(如 fetchIntersectionObserver)。

    • CSS 属性在某些浏览器中需要前缀(如 -webkit--moz-)。

  • 解决方案:

    1. 语法转换与 Polyfill:

      • 工具: 使用 Babel 将 ES6+ 代码转换为 ES5 语法。

      • 配置: 在 babel.config.js 或 .browserslistrc 文件中指定需要兼容的浏览器范围,Babel 会根据这个范围决定需要转换哪些特性。

      • Polyfill: 对于 Babel 无法转换的 API(如 Promisefetch),需要引入 core-js 和 regenerator-runtime 来模拟实现这些功能。

      javascript

      // 在项目入口文件 (如 main.js) 中引入
      import 'core-js/stable'
      import 'regenerator-runtime/runtime'
    2. 自动化前缀:

      • 工具: 使用 PostCSS 配合 Autoprefixer 插件,它会根据 .browserslistrc 配置自动为 CSS 属性添加供应商前缀。

    3. 条件依赖与动态加载:

      • 对于一些非核心的、只在现代浏览器中性能更好的库(如 IntersectionObserver),可以采用动态 import() 或通过条件判断来加载 Polyfill 或降级方案。

2. Vue 2 到 Vue 3 的迁移兼容性

这是在升级框架版本时遇到的最典型问题。

  • 问题场景:

    • 被移除的 API: 如 $on$off$once 事件总线 API、Filters(过滤器)、Vue.extend 等。

    • 行为改变的 API: 如 v-model 的用法、keyCode 修饰符、$listeners 被合并到 $attrs 等。

    • 生命周期钩子名称变化: destroyed -> unmounted

  • 解决方案:

    1. 使用官方迁移指南和工具:

      • 第一步: 仔细阅读 Vue 3 迁移指南,这是最重要的参考资料。

      • 第二步: 使用官方提供的 迁移构建版本 (Migration Build)。它在 Vue 3 运行时中提供了 Vue 2 兼容行为,并在你使用已移除/改变的 API 时发出警告。这让你可以逐步修改代码,而不是一次性重写。

      • 第三步: 运行 vue-upgrade 工具,它可以自动检测代码库中需要修改的地方。

    2. 渐进式重构:

      • 对于大型项目,一次性迁移风险太高。可以采用“渐进式迁移”策略:

        • 将项目构建工具(如 Webpack)配置为同时支持 Vue 2 和 Vue 3 包。

        • 新写的组件使用 Vue 3 的 Composition API。

        • 旧的 Vue 2 组件暂时保留,逐步重构。

    3. 替代方案:

      • 事件总线: 用 mitt 或 tiny-emitter 这类第三方库替代 $on/$off

      • 过滤器: 用计算属性或方法替代。

      • 全局 API 变更: 将 Vue.prototype 的修改改为使用 app.config.globalProperties

3. 第三方库兼容性
  • 问题场景:

    • 项目依赖的某个第三方库(如 UI 组件库、工具库)尚未支持 Vue 3。

  • 解决方案:

    1. 检查官方仓库: 首先去该库的 GitHub 或官网查看是否有支持 Vue 3 的版本。很多流行库(如 Element Plus, Vant, Ant Design Vue)都提供了 Vue 3 版本。

    2. 寻找替代品: 如果原库不再维护,寻找一个功能相似且支持 Vue 3 的替代库。

    3. 自己封装或降级: 如果是小功能,可以考虑自己实现。如果暂时无法替换,可以考虑在 Vue 3 项目中使用 vue-demi 来尝试兼容,但这通常是临时方案。


举例说明(让回答更具体)

“让我举一个具体的例子。在我们将项目从 Vue 2 升级到 Vue 3 的过程中,遇到了一个典型问题:我们之前大量使用了 Event Bus 进行组件间通信。

  • 问题: Vue 3 移除了 $on$off 这些实例方法,导致所有通过 new Vue() 创建的 Event Bus 全部失效,控制台报错。

  • 排查: 我们运行了官方的迁移构建版本,它清晰地警告了我们正在使用已移除的 API。然后我们通过全局搜索 $on 和 $off,定位了所有使用 Event Bus 的文件。

  • 解决:

    1. 我们评估了通信场景,对于一些简单的跨组件通信,我们用 Vue 3 的 provide/inject 进行了重构。

    2. 对于更复杂的、需要事件监听和发射的场景,我们引入了官方推荐的轻量级库 mitt

    3. 我们将原来的 const bus = new Vue() 替换为 const bus = mitt()

    4. 将 bus.$on('event', handler) 改为 bus.on('event', handler)

    5. 将 bus.$off('event', handler) 改为 bus.off('event', handler)

  • 结果: 通过这种方式,我们以最小的代价平滑地解决了这个兼容性问题,并且代码更加现代化和清晰。”

总结与预防

“通过处理这些兼容性问题,我总结出的经验是:

  1. 预防优于解决: 在项目启动时,就通过 .browserslistrc 和 package.json 的 engines 字段明确目标环境。

  2. 依赖管理: 定期更新依赖,关注核心库(如 Vue、React)的发布动态和破坏性更新预告。

  3. 工具化: 善用官方提供的迁移工具和林格(ESLint)规则,它们能提前发现大部分潜在问题。

  4. 渐进策略: 对于大型项目的升级,不要追求一步到位,采用渐进式、可回滚的方案更为稳妥。

4.在pc当中上传图片,在小程序当中进行展示,假设在小程序当中图片所呈现的大小比例都固定,如何处理pc的图片,在小程序当中显示是不会被拉伸的
方案一:使用 CSS object-fit 属性(推荐)
  • object-fit: cover (CSS) / mode="aspectFill" (小程序):

    • 保持图片原始比例缩放

    • 确保图片完全覆盖容器

    • 可能会裁剪掉图片的边缘部分

    • 适用场景: 头像、商品主图、 banner 等,确保容器被填满且视觉重点在中央的情况

  • object-fit: contain (CSS) / mode="aspectFit" (小程序):

    • 保持图片原始比例缩放

    • 确保整个图片都在容器内可见

    • 容器可能会有留白

    • 适用场景: 需要完整展示图片内容,如证件照、详细产品图等

.container {width: 300px;  /* 容器固定宽度 */height: 200px; /* 容器固定高度 (3:2比例) */overflow: hidden;
}.adaptive-image {width: 100%;height: 100%;object-fit: cover; /* 关键属性 */
}
<!-- 在小程序WXML中 -->
<view class="container"><image class="adaptive-image" src="{{imageUrl}}" mode="aspectFill"></image>
</view>
方案二:背景图方式(灵活控制)
.image-container {width: 300px;height: 200px;background-position: center center;background-repeat: no-repeat;background-size: cover; /* 或 contain */
}
<view class="image-container" style="background-image: url({{imageUrl}})"
></view>
方案三:服务端预处理(终极解决方案)
// 服务端处理示例 (Node.js + Sharp库)
const sharp = require('sharp');async function processImageForMiniProgram(inputPath, outputPath) {// 定义小程序展示的标准尺寸const TARGET_WIDTH = 750;const TARGET_HEIGHT = 500; // 3:2比例await sharp(inputPath).resize(TARGET_WIDTH, TARGET_HEIGHT, {fit: 'cover',    // 覆盖模式position: 'center' // 从中心开始裁剪}).toFile(outputPath);
}
方案四:动态计算 + 定位(精确控制)
// 在小程序JS中计算图片位置
Page({data: {imageStyle: ''},onImageLoad(e) {const { width, height } = e.detail;const containerRatio = 3/2; // 容器宽高比const imageRatio = width / height;let style = '';if (imageRatio > containerRatio) {// 图片较宽,需要水平居中裁剪const displayWidth = height * containerRatio;const offsetX = (width - displayWidth) / 2;style = `width: auto; height: 100%; margin-left: -${offsetX/width*100}%`;} else {// 图片较高,需要垂直居中裁剪  const displayHeight = width / containerRatio;const offsetY = (height - displayHeight) / 2;style = `width: 100%; height: auto; margin-top: -${offsetY/height*100}%`;}this.setData({ imageStyle: style });}
})
<view class="container"><image src="{{imageUrl}}" style="{{imageStyle}}"bindload="onImageLoad"></image>
</view>
实际项目中的综合策略

"在实际项目中,我通常会采用分层策略:

  1. 前端基础保障: 使用 object-fit: cover 或小程序的 mode="aspectFill" 作为基础方案

  2. 重要图片服务端预处理: 对于商品主图、用户头像等重要图片,在上传时进行智能裁剪和优化

  3. 用户体验优化:

    • 添加加载状态和错误处理

    • 使用CDN加速图片加载

    • 实现懒加载减少初始加载压力

// 上传时的处理建议
const uploadStrategies = {// 用户头像:严格正方形裁剪avatar: { width: 200, height: 200, fit: 'cover' },// 商品主图:3:2比例product: { width: 750, height: 500, fit: 'cover' },// 详情图片:保持原比例,宽度固定detail: { width: 750, height: null, fit: 'inside' }
};

http://www.dtcms.com/a/461504.html

相关文章:

  • 【pyTorch】关于PyTorch的高级索引机制理解
  • c++ bug 函数定义和声明不一致导致出bug
  • 网站建设需求分析文档手机上制作ppt的软件
  • 推广网站怎么做能增加咨询南宁企业官网seo
  • MATLAB的无线传感器网络(WSN)算法仿真
  • k8s opa集成
  • Nginx 负载均衡通用方案
  • 我的世界怎么做神器官方网站dw网站设计与制作
  • ubuntu22.04发布QT程序步骤
  • Spring Boot:分布式事务高阶玩法
  • 做网站开什么端口网址格式
  • 白云区建设局网站建筑工程网教
  • react native android设置邮箱,进行邮件发送
  • Java面试场景:从Spring Boot到Kubernetes的技术问答
  • 从潜在空间到实际应用:Embedding模型架构与训练范式的综合解析
  • Vue3 provide/inject 详细组件关系说明
  • php的网站架构建设框架嘉兴网站设计
  • Redis(四)——Redis主从同步与对象模型
  • 2016年网站建设总结培训学校
  • 网站最下端怎么做动画设计培训机构
  • 用python制作相册浏览小工具
  • 字节跳动ByteDance前端考前总结
  • codex使用chrome-devtools-mcp最佳实践
  • 【Linux命令从入门到精通系列指南】export 命令详解:环境变量管理的核心利器
  • python 自动化采集 ChromeDriver 安装
  • 苏州招聘网站建设推广费
  • java8提取list中对象有相同属性值的对象或属性值
  • cuda编程笔记(26)-- 核函数使用任务队列
  • 存储芯片核心产业链研发实力:兆易创新、北京君正、澜起科技、江波龙、长电科技、佰维存储,6家龙头公司研发实力深度数据
  • 《Seq2Time: Sequential Knowledge Transfer for Video LLMTemporal Grounding》