框架是什么(前端框架是什么)( 二 )


Vue是一个组件级的数据手表 。当组件内部有大量监控数据更改时 , 更新可能会计算量很大 , 这可能会导致丢帧 , 即渲染停滞 。所以vue的优化方法是把大组件拆分成小组件 , 这样每个数据就不会有太多的watcher 。
React不监听数据变化 , 而是渲染整个虚拟dom , 然后diff 。基于该方案的优化方法是 , 对于不需要重新生成vdom的组件 , 通过shouldComponentUpdate跳过渲染 。
但是当应用的组件树特别大的时候 , 只有shouldComponentUpdate跳过了一些组件的渲染 , 计算量可能还是特别大 。计算量过大 , 也可能导致卡顿渲染怎么办?
【框架是什么(前端框架是什么)】树的遍历有两种方式:深度优先和广度优先 。组件树的渲染是深度优先的 , 通常是通过递归来完成 , 但是如果路径可以通过链表记录 , 就可以变成循环 。当它变成一个循环时 , 可以按照时间片进行分段 , 这样vdom的生成就不会再阻塞页面渲染 , 就像操作系统对多个进程的分时调度一样 。
把组件树改成链表 , 把vdom的生成从递归改成循环 , 函数就是react fiber 。
与前面的组件节点相比 , 纤程节点不具有父节点和子节点的属性 , 而是具有子节点、兄弟节点和返回节点的属性 。
通过纤程链表树 , 优化了渲染性能 。
可以看出 , vue的性能优化与react不同:
Vue是一个组件级的数据监控方案 , 当一个属性中有太多的观察者时可能会出现问题 , 所以优化的思路是把大的组件拆分成小的组件 , 保证每个属性没有太多的观察者 。
React不监控和检查数据变化 , 每次渲染生成vdom , 然后对比vdom 。然后优化的思路是shouldComponentUpdate跳过一些组件的渲染 , 在react内部做一个组件树的链表 , 把递归变成可中断的渲染 , 按照时间片逐步生成整个vdom 。
组件之间必然存在逻辑复用 , react和vue有不同的方案:
vue的组件是option对象的方式 , 所以很自然的想到了通过对象属性mixin的逻辑复用方式 , vue2中的逻辑复用方案就是mixin 。但是mixin很难区分混合属性和方法的来源 , 比较混乱 , 代码可维护性差 。但是没有更好的计划了 。
一开始react还支持mixin , 后来就放弃了 。
react的组件有类和函数两种形式 , 所以高阶组件类似于高阶函数的方式更加自然 , 即组件嵌套 , 在父组件中执行一些逻辑 , 然后渲染子组件 。
除了多加一层组件的HOC模式 , 不合逻辑的部分可以直接把jsx的那部分作为道具传递给另一个组件重用 , 也就是渲染道具 。
和HOC渲染道具是react的类组件支持的两种逻辑重用方案 。
一开始 , 函数组件没有状态 , 只是作为渲染类组件的辅助而存在 。
但HOC的逻辑复用方式最终导致组件嵌套过深 , 类内部生命周期多 , 逻辑放在一起 , 导致组件相对庞大 。
如何解决嵌套深 , 类组件大的问题?而且不能引入破坏性的更新 , 不然结局可能会很惨 。
所以react团队好好看了看函数组件 , 看它是否也能在函数组件中支持状态 , 通过扩展一些API来支持它 , 并不是破坏性更新 。
功能组件应该支持状态 , 那么状态存在于哪里呢?
类节点有一个状态 , 在它成为纤程节点后仍然存在 。功能组件根本没有状态 , 所以纤程节点中也没有状态 。
为什么不直接给函数组件的纤程节点添加状态呢?
然后react将memorizedState属性添加到函数组件的纤程节点中存储数据 , 然后通过api使用函数组件中的数据 , 这些API称为hooks api 。
因为使用了纤程节点上的数据 , 所以这个api被命名为useXxx 。
每个钩子api都应该有自己的位置来存储数据 。怎么组织?有两种方案 , 一种是map , 一种是array 。
如果使用map , 那么hooks api应该指定键 , 并根据键访问纤程节点中的数据 。
如果使用array , 顺序是不能改变的 , 所以hooks api不能出现在If之类的逻辑块中 , 只能出现在顶层 。


推荐阅读