1.什么是重绘和回流,有哪些措施可以避免回流,从而提高页面性能
重绘(repaint)和回流(reflow)是浏览器渲染页面时的两个重要的步骤。
重绘是指当一个元素的样式(如颜色、背景等)发生变化,但没有影响其布局(如位置、大小等)时,浏览器会将这个元素的新样式重新画到页面上。
回流则是指当一个元素的布局发生变化时,浏览器需要重新计算该元素在页面中的位置和大小,并且需要重新布局相关元素,这个过程可能会导致整个页面其他部分的重新渲染。
由于回流会涉及到多个元素的重新计算和布局,因此它的成本要比重绘更高,会对页面性能产生较大的影响。
为了避免回流,可以采取以下几个措施:
-
减少 DOM 操作:DOM 的增删改操作会引起回流,因此尽量减少这些操作,可以通过使用文档碎片、虚拟 DOM 等技术来优化。
-
使用 CSS3 动画代替 JavaScript 动画:CSS3 动画由浏览器自己处理,不会触发 JavaScript 脚本,因此可以避免回流。
-
避免频繁读取 offsetLeft、offsetTop 等属性:这些属性的读取会导致回流,如果需要多次读取,可以将其缓存起来。
-
使用 transform 和 opacity 属性:这两个属性不会触发回流,可以用来实现元素的动画效果。
-
避免使用 table 布局:table 的布局方式比较复杂,可能会导致频繁的回流,可以使用 div 布局代替。
通过上述措施的实践,可以显著提高页面性能,使用户的体验更加流畅和舒适。
2.什么是 BFC
BFC(块级格式化上下文)是前端开发中的一个重要概念,它是指一个独立的渲染区域,规定了内部元素如何布局,并且与外部元素互相隔离。在一个BFC中,所有的子元素会根据一定的规则进行布局,这些规则包括:浮动、清除浮动、尺寸计算、边距折叠等。
前端BFC可以解决一些常见的布局问题,例如:父容器和子元素之间的margin折叠问题、浮动元素造成的高度塌陷问题等。通过创建一个BFC,我们可以让元素具有一定的独立性,从而实现更加灵活的布局。
在HTML中,可以通过以下方式来创建一个BFC:
- float属性不为none;
- position属性为absolute或fixed;
- display属性为inline-block、table-cell、table-caption;
- overflow属性不为visible。
值得注意的是,创建BFC的元素之间也不会影响彼此的布局,因此在设计复杂页面时,合理利用BFC可以帮助我们简化布局,提高开发效率。
3.vue 实现数据绑定以及页面dom更新机制
Vue实现数据绑定和页面DOM更新的机制,主要依靠响应式系统和虚拟DOM技术。
- 响应式系统
Vue使用了一种称为响应式系统的观察者模式来监听数据的变化。当一个组件实例创建时,Vue会遍历data选项中的属性,对每个属性都使用Object.defineProperty方法将其转化为getter/setter,并且在内部建立一个依赖收集器(Dep),用来收集当前属性的所有订阅者(Watcher)。
当数据发生改变时,setter就会被调用,setter会通知依赖收集器向订阅该属性的所有Watcher发送通知,告诉它们数据已经发生了变化。Watcher接收到通知后,会重新计算表达式的值,并且更新视图。
- 虚拟DOM技术
Vue使用了虚拟DOM技术来优化DOM操作。当组件的数据发生变化,Vue会先将数据转换为虚拟DOM对象,并将其与上一次渲染的虚拟DOM进行比较,得出需要更新的部分,然后只更新这些部分的真实DOM,而不是全部重新渲染整个组件。这样可以减少DOM操作的次数,提高性能。
总的来说,Vue的数据绑定和DOM更新机制是通过响应式系统和虚拟DOM技术相结合来实现的。通过响应式系统,Vue能够监听数据变化并自动更新视图,而虚拟DOM技术可以优化DOM操作,提高性能。
4.什么是js原型链
JavaScript中的每个对象都有一个原型,也就是它们继承属性和方法的对象。而这个原型又可以有自己的原型,形成了所谓的“原型链”。
当我们访问一个JavaScript对象的属性或方法时,首先会在该对象本身查找是否存在该属性或方法。如果不存在,它会沿着该对象的原型链向上查找,一直到Object.prototype为止。如果还没有找到,则返回undefined。
因此,通过原型链,我们可以实现继承和代码复用。例如,我们可以创建一个基础对象,并将其作为其他对象的原型,使得后者能够共享基础对象的属性和方法。
5.js中event loop,以及浏览器和node的event loop的异同
- 代码开始执行,创建一个全局调用栈,
script
作为宏任务执行 - 执行过程过同步任务立即执行,异步任务根据异步任务类型分别注册到微任务队列和宏任务队列
- 同步任务执行完毕,查看微任务队列
- 若存在微任务,将微任务队列全部执行(包括执行微任务过程中产生的新微任务)
- 若无微任务,查看宏任务队列,执行第一个宏任务,宏任务执行完毕,查看微任务队列,重复上述操作,直至宏任务队列为空
- 宏任务(script、定时器、ajax、I/O);微任务(promise.then、async await、MutationObserve 监听dom变化)