Vue 面试


Vue 怎么用 vm.$set() 解决对象新增属性不能响应的问题 ?

受现代 JavaScript 的限制 ,Vue 无法检测到对象属性的添加或删除。
由于 Vue 会在初始化实例时对属性执行 getter/setter 转化,所以属性必须在 data 对象上存在才能让 Vue 将它转换为响应式的。
但是 Vue 提供了 Vue.set (object, propertyName, value) / vm.$set (object, propertyName, value)来实现为对象添加响应式属性,那框架本身是如何实现的呢?

  • 我们查看对应的 Vue 源码:vue/src/core/instance/index.js
export function set (target: Array<any> | Object, key: any, val: any): any { // target 为数组 if (Array.isArray(target) && isValidArrayIndex(key)) { // 修改数组的长度, 避免索引>数组长度导致splcie()执行有误 target.length = Math.max(target.length, key) // 利用数组的splice变异方法触发响应式 target.splice(key, 1, val) return val } // key 已经存在,直接修改属性值 if (key in target && !(key in Object.prototype)) {
    target[key] = val return val } const ob = (target: any).__ob__ // target 本身就不是响应式数据, 直接赋值 if (!ob) {
    target[key] = val return val } // 对属性进行响应式处理 defineReactive(ob.value, key, val)
  ob.dep.notify() return val }

我们阅读以上源码可知,vm.$set 的实现原理是:

  • 如果目标是数组,直接使用数组的 splice 方法触发相应式;
  • 如果目标是对象,会先判读属性是否存在、对象是否是响应式,最终如果要对属性进行响应式处理,则是通过调用 defineReactive 方法进行响应式处理( defineReactive 方法就是 Vue 在初始化对象时,给对象属性采用 Object.defineProperty 动态添加 getter 和 setter 的功能所调用的方法)

 虚拟 DOM 的优缺点?

优点:

  • 保证性能下限: 框架的虚拟 DOM 需要适配任何上层 API 可能产生的操作,它的一些 DOM 操作的实现必须是普适的,所以它的性能并不是最优的;但是比起粗暴的 DOM 操作性能要好很多,因此框架的虚拟 DOM 至少可以保证在你不需要手动优化的情况下,依然可以提供还不错的性能,即保证性能的下限;
  • 无需手动操作 DOM: 我们不再需要手动去操作 DOM,只需要写好 View-Model 的代码逻辑,框架会根据虚拟 DOM 和 数据双向绑定,帮我们以可预期的方式更新视图,极大提高我们的开发效率;
  • 跨平台: 虚拟 DOM 本质上是 JavaScript 对象,而 DOM 与平台强相关,相比之下虚拟 DOM 可以进行更方便地跨平台操作,例如服务器渲染、weex 开发等等。

缺点:

  • 无法进行极致优化: 虽然虚拟 DOM + 合理的优化,足以应对绝大部分应用的性能需求,但在一些性能要求极高的应用中虚拟 DOM 无法进行针对性的极致优化。

虚拟 DOM 实现原理?

虚拟 DOM 的实现原理主要包括以下 3 部分:

  • 用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象;
  • diff 算法 — 比较两棵虚拟 DOM 树的差异;
  • pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。

Vue 中的 key 有什么作用?

key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速。
Vue 的 diff 过程可以概括为:oldCh 和 newCh 各有两个头尾的变量 oldStartIndex、oldEndIndex 和 newStartIndex、newEndIndex,它们会新节点和旧节点会进行两两对比,即一共有4种比较方式:newStartIndex 和oldStartIndex 、newEndIndex 和 oldEndIndex 、newStartIndex 和 oldEndIndex 、newEndIndex 和 oldStartIndex,如果以上 4 种比较都没匹配,如果设置了key,就会用 key 再进行比较,在比较的过程中,遍历会往中间靠,一旦 StartIdx > EndIdx 表明 oldCh 和 newCh 至少有一个已经遍历完了,就会结束比较。
所以 Vue 中 key 的作用是:key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速!

  • 更准确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。
  • 更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快,源码如下:
function createKeyToOldIdx (children, beginIdx, endIdx) { let i, key const map = {} for (i = beginIdx; i <= endIdx; ++i) {
    key = children[i].key if (isDef(key)) map[key] = i
  } return map
}

 你有对 Vue 项目进行哪些优化?

(1)代码层面的优化

  • v-if 和 v-show 区分使用场景
  • computed 和 watch 区分使用场景
  • v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
  • 长列表性能优化
  • 事件的销毁
  • 图片资源懒加载
  • 路由懒加载
  • 第三方插件的按需引入
  • 优化无限列表性能
  • 服务端渲染 SSR or 预渲染

(2)Webpack 层面的优化

  • Webpack 对图片进行压缩
  • 减少 ES6 转为 ES5 的冗余代码
  • 提取公共代码
  • 模板预编译
  • 提取组件的 CSS
  • 优化 SourceMap
  • 构建结果输出分析
  • Vue 项目的编译优化

(3)基础的 Web 技术的优化

  • 开启 gzip 压缩
  • 浏览器缓存
  • CDN 的使用
  • 使用 Chrome Performance 查找性能瓶颈
#涂鸦智能实习#
全部评论
多看点面经,我也涨点经验
点赞 回复 分享
发布于 2022-08-24 10:15 江苏

相关推荐

03-12 12:54
已编辑
武汉理工大学 前端工程师
一面&nbsp;2.10##&nbsp;预计时长60min##&nbsp;实际时长51min1.&nbsp;对于部门的背景和这次面试有什么想问的吗2.&nbsp;我看到你现在是在百度实习,可以讲讲这个业务吗3.&nbsp;跨端做的是IOS还是安卓4.&nbsp;你对整个架构有什么理解吗,比如离线包这一块,比如离线包解决什么样的问题,离线包是怎么下发和更新的5.&nbsp;如果说不用离线包,在app上打开一个http地址,这个页面会有什么问题6.&nbsp;离线包除了快还有什么优势7.&nbsp;React18新特性有了解吗8.&nbsp;在没有这些特性之前,react是怎么调度的,有了之后是怎么调度的9.&nbsp;fiber本身是为了解决什么样的问题10.&nbsp;如果没有fiber,diff的时候会怎么样,会不会有一些性能瓶颈11.&nbsp;平时ts用的多吗12.&nbsp;讲讲泛型,如果现在要通过泛型传入一个string进去,希望推导出来的结果也是string,怎么做13.&nbsp;平时用vue还是react多一点14.&nbsp;讲一下react中常用的hooks15.&nbsp;useLayoutEffect和useEffect有什么区别16.&nbsp;useEffect中可以返回一个函数,这个函数什么时候会执行17.&nbsp;平时有没有对项目做一些性能优化18.&nbsp;除了资源相关的优化,还能在哪些方面做优化19.&nbsp;在浏览器中从输入URL到页面加载完毕的过程是什么(引出可优化的内容)20.&nbsp;有了解过http2.0吗,可以讲一下他的一些特性吗21.&nbsp;二进制帧如果丢失,重传机制是怎么样的22.&nbsp;TCP和UDP的区别23.&nbsp;TCP是怎么去实现可靠传输的手撕:深拷贝(后续又延伸问了处理除了对象和数组类型之外的数据的思路)24.&nbsp;反问及建议二面&nbsp;2.11预计45min实际90min1.&nbsp;自我介绍2.&nbsp;介绍一下实习期间项目里面的一些技术难点,具体是怎么解决的3.&nbsp;针对刚刚提到的具体的优化,量化指标是怎么样的,如何验证优化是否有效4.&nbsp;再针对个人项目里面,挑一个难点讲一下,想听到的是分析过程,如何拆解问题5.&nbsp;共享屏幕启动项目看效果6.&nbsp;代码是AI写的还是自己写的7.&nbsp;用的是什么AI,怎么去使用ai来完成一个功能或一个项目8.&nbsp;有没有在ai的rules或者skills方面做具体的沉淀算法:1.&nbsp;LRU缓存2.&nbsp;大数相加,自己去写一些测试用例并验证3.&nbsp;思考题:现在有假设一栋楼有100层,你有两个玻璃球,有些楼层扔下去球会碎,有些不会碎,你需要利用这两个球,找到那个临界楼层,最优的解法是什么反问二面狂面90分钟直接燃尽,面完过年了一直到年后才约面三面&nbsp;3.4预计时长:60min实际时长:68min##&nbsp;1.&nbsp;自我介绍##&nbsp;2.&nbsp;聊实习##&nbsp;3.&nbsp;有没有考虑过计费或者说成本,或者说对于服务端的压力,比如说CDN的(针对实习亮点)##&nbsp;4.&nbsp;对于国际化开发和国内开发的区别,有没有什么心得感受##&nbsp;5.&nbsp;多语言工具用的是什么,原理是什么##&nbsp;6.&nbsp;怎么判断用户当前应该使用的是什么语言##&nbsp;7.&nbsp;实习中还有什么对自己提升是比较大的##&nbsp;8.&nbsp;对于跨端架构的几种方案,如何进行选择(h5,native等)##&nbsp;9.&nbsp;现在在跨端架构中如果使用webview加载离线包的方案,如果在端内点击一个下载按钮,整个调用链路和过程是怎么样的##&nbsp;10.&nbsp;端侧的方法是如何注入到web中的##&nbsp;11.&nbsp;聊个人项目,做这个项目的初衷是什么,为了解决什么问题##&nbsp;12.&nbsp;项目中的ai主要用来解决什么问题##&nbsp;13.&nbsp;调用一次模型成本是多少,输入和输出谁消耗的token更多##&nbsp;14.&nbsp;langchain.js框架解决了什么事情##&nbsp;15.&nbsp;现在写代码都是自己写吗,如何使用好ai##&nbsp;16.&nbsp;实习过程中团队会去应用rules或者skills吗,是怎么用的,是为了解决什么问题##&nbsp;17.&nbsp;如果现在对于这几个月的实习去做一个总结,会从哪些方面去进行总结##&nbsp;18.&nbsp;实习过程中有没有存在对于一个需求,自己方案和mt的方案不一致的情况,如果有,是怎么解决的##&nbsp;19.&nbsp;反问HR面&nbsp;3.6都是常规问题3.12&nbsp;offer
点赞 评论 收藏
分享
评论
3
13
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务