into-piece / Step-By-Step

每天一题向前端架构师前进
4 stars 1 forks source link

20200525 #33

Open into-piece opened 4 years ago

into-piece commented 4 years ago

event-loop

回流,重绘与合成的区别,如何优化

浏览器层合成

浏览器渲染流程

一般可以分为:构建 DOM 树、构建渲染树、布局、绘制、渲染层合成 几个步骤。

渲染层合成

在 DOM 树中每个节点都会对应一个渲染对象(RenderObject),当它们的渲染对象处于相同的坐标空间(z 轴空间)时,就会形成一个 RenderLayers,也就是渲染层。渲染层将保证页面元素以正确的顺序堆叠,这时候就会出现层合成(composite),从而正确处理透明元素和重叠元素的显示。 这个模型类似于 Photoshop 的图层模型,在 Photoshop 中,每个设计元素都是一个独立的图层,多个图层以恰当的顺序在 z 轴空间上叠加,最终构成一个完整的设计图。 对于有位置重叠的元素的页面,这个过程尤其重要,因为一旦图层的合并顺序出错,将会导致元素显示异常。

为什么react使用fiber 做时间分片不用generator

  1. 必须将每个函数包装在生成器中。 这不仅增加了很多语法开销,而且还增加了任何现有实现中的运行时开销。
  2. 但是,最大的原因是生成器是有状态的。 您无法在其中途恢复。
function* doWork(a, b, c) {
  var x = doExpensiveWorkA(a);
  yield;
  var y = x + doExpensiveWorkB(b);
  yield;
  var z = y + doExpensiveWorkC(c);
  return z;
}

如果要跨多个时间段执行此操作,则可以逐步执行。 但是,如果我已经完成doExpensiveWorkA(a)和doExpensiveWorkB(b)但没有完成doExpensiveWorkC(c)时获得了对B的更新,则我无法重用值x。 即 跳过具有不同b值的doExpensiveWorkB,但仍重用doExpensiveWorkA(a)的结果。

这对React很重要,因为我们做了大量的缓存。

可以将其添加为周围的层,这似乎是合理的,但实际上,使用generators并没有带来太多好处。

也有一些语言具有generators,这些generators是为具有此功能的更实用的用例而设计的。JS不是其中之一。

React 原生动态加载

react-lazy

React.lazy 接受一个函数作为参数,这个函数需要调用 import() 。它需要返回一个 Promise,该 Promise 需要 resolve 一个 defalut export 的 React 组件。

在控制台打印可以看到,React.lazy 方法返回的是一个 lazy 组件的对象,类型是 react.lazy,并且 lazy 组件具有 _status 属性,与 Promise 类似它具有 Pending、Resolved、Rejected 三个状态,分别代表组件的加载中、已加载、和加载失败三中状态。

需要注意的一点是,React.lazy 需要配合 Suspense 组件一起使用,在 Suspense 组件中渲染 React.lazy 异步加载的组件。如果单独使用 React.lazy,React 会给出错误提示。

Suspense 组件中,fallback 是一个必需的占位属性,如果没有这个属性的话也是会报错的。

在动态加载的组件资源比较小的情况下,会出现 fallback 组件一闪而过的的体验问题,如果不需要使用可以将 fallback 设置为 null。

当然针对这种场景,React 也提供了对应的解决方案,在 Concurrent Mode 模式下,给Suspense 组件设置 maxDuration 属性,当异步获取数据的时间大于 maxDuration 时间时,则展示 fallback 的内容,否则不展示。

 <Suspense 
   maxDuration={500} 
   fallback={<div>抱歉,请耐心等待 Loading...</div>}
 >
   <OtherComponent />
   <OtherComponentTwo />
</Suspense>

Suspense 可以包裹多个动态加载的组件,这也意味着在加载这两个组件的时候只会有一个 loading 层,因为 loading 的实现实际是 Suspense 这个父组件去完成的,当所有的子组件对象都 resolve 后,再去替换所有子组件。这样也就避免了出现多个 loading 的体验问题。所以 loading 一般不会针对某个子组件,而是针对整体的父组件做 loading 处理。

webpack动态加载

webpack 通过创建 script 标签来实现动态加载的,找出依赖对应的 chunk 信息,然后生成 script 标签来动态加载 chunk,每个 chunk 都有对应的状态:未加载 、 加载中、已加载 。

suspense

Error Boundaries

会了就不记录了

babel 原理

https://www.jianshu.com/p/e9b94b2d52e2

babel的转译过程也分为三个阶段:parsing、transforming、generating

ES6代码输入 ==》 babylon进行解析 ==》 得到AST ==》 plugin用babel-traverse对AST树进行遍历转译 ==》 得到新的AST树 ==》 用babel-generator通过AST树生成ES5代码

webpack的优化配置(问到不会自然停) 然后loader plugin的写法 然后就再深点就源码(不会) ES6 怎么转成ES5? 请简述 babel 的工作原理 为什么用ast啊

nextTick 微任务宏任务 双向数据绑定

然后Object.defineProperty 还有 proxy

打开页面的时候先出现无样式的页面 然后出现有样式的页面是怎么回事? 专业术语叫什么?原理

https://nextfe.com/how-chrome-compute-css/