把 DOM 离线后修改,比如:先把 DOM 给 display:none(有一次 Reflow),然后你修改100次,然后再把它显示出来
不要把 DOM 结点的属性值放在一个循环里当成循环里的变量for(let i = 0; i < 1000; i++) {// 获取 offsetTop 会导致回流,因为需要去获取正确的值console.log(document.querySelector('.test').style.offsetTop)}
参考答案
vue和react都是采用diff算法来对比新旧虚拟节点,从而更新节点 。在vue的diff函数中(建议先了解一下diff算法过程) 。在交叉对比中,当新节点跟旧节点头尾交叉对比没有结果时,会根据新节点的key去对比旧节点数组中的key,从而找到相应旧节点(这里对应的是一个key => index 的map映射) 。如果没找到就认为是一个新增节点 。而如果没有key,那么就会采用遍历查找的方式去找到对应的旧节点 。一种一个map映射,另一种是遍历查找 。相比而言 。map映射的速度更快 。vue部分源码如下:// vue项目src/core/vdom/patch.js-488行// 以下是为了阅读性进行格式化后的代码// oldCh 是一个旧虚拟节点数组if (isUndef(oldKeyToIdx)) {oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)}if(isDef(newStartVnode.key)) {// map 方式获取idxInOld = oldKeyToIdx[newStartVnode.key]} else {// 遍历方式获取idxInOld = findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)}
创建map函数function createKeyToOldIdx (children, beginIdx, endIdx) {let i, keyconst map = {}for (i = beginIdx; i <= endIdx; ++i) {key = children[i].keyif (isDef(key)) map[key] = i}return map}
遍历寻找// sameVnode 是对比新旧节点是否相同的函数 function findIdxInOld (node, oldCh, start, end) {for (let i = start; i < end; i++) {const c = oldCh[i]if (isDef(c) && sameVnode(node, c)) return i}}
2、React 中 setState 什么时候是同步的,什么时候是异步的?参考答案
在React中,如果是由React引发的事件处理(比如通过onClick引发的事件处理),调用setState不会同步更新this.state,除此之外的setState调用会同步执行this.state 。所谓“除此之外”,指的是绕过React通过addEventListener直接添加的事件处理函数,还有通过setTimeout/setInterval产生的异步调用 。**原因:**在React的setState函数实现中,会根据一个变量isBatchingUpdates判断是直接更新this.state还是放到队列中回头再说,而isBatchingUpdates默认是false,也就表示setState会同步更新this.state,但是,有一个函数batchedUpdates,这个函数会把isBatchingUpdates修改为true,而当React在调用事件处理函数之前就会调用这个batchedUpdates,造成的后果,就是由React控制的事件处理过程setState不会同步更新this.state 。
3、下面输出什么
class Example extends React.Component {constructor() {super();this.state = {val: 0};}componentDidMount() {this.setState({val: this.state.val + 1});console.log(this.state.val);// 第 1 次 logthis.setState({val: this.state.val + 1});console.log(this.state.val);// 第 2 次 logsetTimeout(() => {this.setState({val: this.state.val + 1});console.log(this.state.val);// 第 3 次 logthis.setState({val: this.state.val + 1});console.log(this.state.val);// 第 4 次 log}, 0);}render() {return null;}};1、第一次和第二次都是在 react 自身生命周期内,触发时 isBatchingUpdates 为 true,所以并不会直接执行更新 state,而是加入了 dirtyComponents,所以打印时获取的都是更新前的状态 0 。2、两次 setState 时,获取到 this.state.val 都是 0,所以执行时都是将 0 设置成 1,在 react 内部会被合并掉,只执行一次 。设置完成后 state.val 值为 1 。3、setTimeout 中的代码,触发时 isBatchingUpdates 为 false,所以能够直接进行更新,所以连着输出 2,3 。输出: 0 0 2 3
4、为什么虚拟dom会提高性能?参考答案
虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能 。具体实现步骤如下:
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
推荐阅读
- 黑茶天尖是什么茶?
- AMD|AMD Zen4锐龙“龙凤胎”来了:55W功耗、游戏本终于满血
- 三星|旗舰机要换代了!UFS 4.0闪存正式发布:读取可达4200MB/s、速度翻番
- 想摸鱼吗?先掌握这 19 个 css 技巧
- 靠着5个自媒体,新手小白如何赚取第一桶金?
- mysql误删除恢复
- Window查看和杀掉进程
- C++可变参模板
- 路虎|路虎极光“GTA”式越野 一飞冲天!结果惨了:减震、悬架全报废
- 私处面相看你能否聚财