前端面试答案2
双向绑定原理:实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer
,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher
看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep
来专门收集这些订阅者,然后在监听器Observer
和订阅者Watcher
之间进行统一管理的。
vue2与3的双向绑定和实现的优缺点:1. 在Vue中,Object.defineProperty
无法监控到数组下标的变化,
2. Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。
而要取代它的Proxy有以下两个优点:
1. 可以劫持整个对象,并返回一个新对象
2. 有13种劫持操作
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
vue路由实现原理::JS会感知到url的变化,通过这一点,可以用js动态的将当前页面的内容清除掉,然后将下一个页面的内容挂载到当前页面上,这个时候的路由不是后端来做了,而是前端来做,判断页面到底是显示哪个组件,清除不需要的,显示需要的组件。这种过程就是单页应用,每次跳转的时候不需要再请求html文件了。
虚拟dom:
最原始的情况下,框架一旦发现数据发生了变动就对整个页面进行更新。这样的做法效率低下,因为数据的变动而导致的页面变动很可能只是局部的,直接对整个页面进行更新造成了不必要的性能消耗。
所以人们很自然的就会想到将因数据变动而新生成的DOM结构与已经显示出来的DOM结构进行比较,找出两者的不同处,再对这些不同进行重新渲染即可。有的放矢,从而提升性能。
而那个仅在内存中未显示出来的DOM结构就是所谓的虚拟DOM,找出两者不同的算法就是Diff算法。
不过需要注意的是,虚拟DOM和Diff算法的出现是为了解决由命令式编程转变为函数式编程、数据驱动后所带来的性能问题的。换句话说,直接操作DOM的性能并不会低于虚拟DOM和Diff算法,甚至还会优于。
compare属性:
computed
会搜集并记录依赖。- 依赖发生了变化才会重新计算
computed
,由于computed
是有缓存的,所以当依赖变化之后,第一次访问computed
属性的时候,才会计算新的值。 - 只能搜集到响应式属性依赖,无法搜集到非响应式属性依赖。
- 无法搜集到当前
vm
实例之外的属性依赖
nextTick
,将等待DOM渲染完成后需要的操作放在回调函数里。(a)浏览器判定是否有缓存
(b)缓存是否过期
(b)过程执行完后,如果判定为未过期,则使用客户端缓存。那么就是属于“强缓存”。
(c)跟服务器协商是否使用缓存
(d)协商缓存
vue优化方案:
对路由组件进行懒加载
v-if 和 v-show选择调用
v-show和v-if的区别是:v-if是懒加载,当状态为true时才会加载,并且为false时不会占用布局空间;v-show是无论状态是true或者是false,都会进行渲染,并对布局占据空间对于在项目中,需要频繁调用,不需要权限的显示隐藏,可以选择使用v-show,可以减少系统的切换开销。
为item设置唯一key值,
在列表数据进行遍历渲染时,需要为每一项item设置唯一key值,方便vuejs内部机制精准找到该条列表数据。当state更新时,新的状态值和旧的状态值对比,较快地定位到diff。
细分vuejs组件
在项目开发过程之中,第一版本把所有的组件的布局写在一个组件中,当数据变更时,由于组件代码比较庞大,vuejs的数据驱动视图更新比较慢,造成渲染比较慢。造成比较差的体验效果。所以把组件细分,比如一个组件,可以把整个组件细分成轮播组件、列表组件、分页组件等。
减少watch的数据
当组件某个数据变更后需要对应的state进行变更,就需要对另外的组件进行state进行变更。可以使用watch监听相应的数据变更并绑定事件。当watch的数据比较小,性能消耗不明显。当数据变大,系统会出现卡顿,所以减少watch的数据。其它不同的组件的state双向绑定,可以采用事件中央总线或者vuex进行数据的变更操作。
内容类系统的图片资源按需加载
对于内容类系统的图片按需加载,如果出现图片加载比较多,可以先使用v-lazy之类的懒加载库或者绑定鼠标的scroll事件,滚动到可视区域先再对数据进行加载显示,减少系统加载的数据。
SR(服务端渲染)
如果项目比较大,首屏无论怎么做优化,都出现闪屏或者一阵黑屏的情况。可以考虑使用SSR(服务端渲染),vuejs官方文档提供next.js很好的服务端解决方案,但是局限性就是目前仅支持Koa、express等Nodejs的后台框架,需要webpack支持。目前自己了解的就是后端支持方面,vuejs的后端渲染支持php,其它的不太清楚。
vue渲染大量数据时处理:
1. 异步渲染组件:因为组件渲染太多,影响页面的渲染时间,所有可以延迟组件渲染,可以考虑v-if处理
2. 可以使用虚拟滚动的组件:参考使用这个插件
vue首屏优化:
1、压缩代码
无论是否为单页应用,代码的压缩都是要做的。
对于vue-cli生成的项目,在Webpack配置文件中使用了UglifyJsPlugin进行代码的压缩:
2、框架和插件按需加载
对于项目中用到的一些UI框架,比如 Onsen UI 、Mint UI 等等。如果我们只使用框架的部分组件,那么可以不要引入整个框架,按需引入用到的组件
3、框架和插件从cdn中引入
在开发过程中,我们其实不会要去更改这些第三方库,所以可以把它们放到cdn中,不参与打包。
在 index.html 中使用cdn引入
4、路由懒加载
路由懒加载也就是 把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件。
结合 Vue 的异步组件和 Webpack 的代码分割功能,轻松实现路由组件的懒加载。
、
重绘与重排
1>重排(Reflow):当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。
2>重绘(Repaint):是在一个元素的外观被改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。比如改变某个元素的背景色、文字颜色、边框颜色等等
3>引发重排
1.添加、删除可见的dom
2.元素的位置改变
3.元素的尺寸改变(外边距、内边距、边框厚度、宽高、等几何属性)
4.页面渲染初始化
5.浏览器窗口尺寸改变
6.获取某些属性。当获取一些属性时,浏览器为取得正确的值也会触发重排,它会导致队列刷新,这些属性包括:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。所以,在多次使用这些值时应进行缓存。
4>优化:
浏览器自己的优化:
浏览器会维护1个队列,把所有会引起重排,重绘的操作放入这个队列,等队列中的操作到一定数量或者到了一定时间间隔,浏览器就会flush队列,进行一批处理,这样多次重排,重绘变成一次重排重绘
减少 reflow/repaint:
(1)不要一条一条地修改 DOM 的样式。可以先定义好 css 的 class,然后修改 DOM 的 className。
(2)不要把 DOM 结点的属性值放在一个循环里当成循环里的变量。
(3)为动画的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他们的 CSS 是不会 reflow 的。
(4)千万不要使用 table 布局。因为可能很小的一个小改动会造成整个 table 的重新布局。(table及其内部元素除外,它可能需要多次计算才能确定好其在渲染树中节点的属性,通常要花3倍于同等元素的时间。这也是为什么我们要避免使用table做布局的一个原因。)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY