查看原文
其他

React 18 之画师登仙!

Linton Ye 博文视点Broadview 2022-08-23

👆点击“博文视点Broadview”,获取更多书讯



我莫名地发现自己坐在一座庙宇的大殿中,周围的人有老有小、衣着各异,但似乎人人都眼神木讷、正襟危坐。

这是个什么鬼地方?

我正四处打量,忽然有人轻轻敲击我的后背,我转过身去,看到一个大概二十出头的女孩。她俏皮地笑了笑,把食指竖在唇前,示意我不要出声。顺着她手指的方向,透过前排的间隙,我向大殿中央望去。

只见那里端坐一人,身披黄色锦袍,右手握着一支一米多长的硕大毛笔,正在面前的画布上运笔如飞。

我想,敢情是网红画家现场表演?怪不得那么多人围观。

忽然,一旁的助手将另一幅画布放在黄衣人面前,他也不停笔,伸出另一只手,用一支一模一样的毛笔在新的画布上开始作画。

一心二用、左圆右方啊,有两把刷子!你到底画的是啥?

正寻思间,助手在黄衣人面前加了一幅画布,只见他双手仍然不停笔,竟从锦袍中伸出第三只手,拿着毛笔在这第三幅画布上作画。

我确信没看错!他确实有三只手,拿着三支笔!我惊魂未定,助手却又拿出三幅画布,尽数都摆在画家面前。

难道他是三头六臂?我不禁倒吸一口气。

果不出所料,画家又多出三只手,六手六笔在六幅画布上同时作画,没有丝毫地犹豫和停顿。

不过这次我看清楚了,他多余的手并不是从锦袍里伸出来的,而是原来的手稍微晃动了一下,在虚影之中不知如何就“分裂”出一只手来,拿着一支同样的毛笔。

这是什么情况?忙于对眼前的景象作出合理解释,我的大脑差点宕机。

只见画家微微点头,最边上的一只手提笔轻轻一顿,似乎是完成了该幅画作。那只手微微晃动了一下,又是一阵虚影,竟然和旁边的一只手合而为一。

在我的瞠目结舌中,画家另外的四只手也纷纷完成画作,虚影之下四合二、二合一,最后只留下形单影只的右手。一阵清风拂过,锦袍空空的左袖随风晃动。

画家随即将手中的画笔凌空一掷,助手稳稳接住,双手高举过头,朗声道:“十八纪元,画师登仙。” 我看见周围众人纷纷拜倒在地。

“其实他就是动作快而已,明明只有一只手却画出了六只手的效果。” 那女孩不知什么时候挤到我身旁,悄声告诉我。“快行礼啊,被画师看见了可不好。” 我这才反应过来,忙不迭地模仿旁人的姿势,但已经太晚。画师目光如炬,早已注意到了我这个不和谐的音符,助手则右手运力,将毛笔如标枪一般朝我掷来。

我大惊之余,急忙躲避,头却撞到旁边不知什么硬物,随即发现自己正趴在家里书桌上,并没有什么庙宇大殿。在我面前也并没有什么画师,而只是电脑屏幕和一本书,封面上写着《坐标 React 星:React 核心思维模型》

我这才记起来,刚才是在赶一篇关于 React 18 的文章(刚刚发布的 React 最新版本),实在太累就趴在桌上休息了一会。我回想起刚才的梦境,看着桌上那本书,那是一本我刚刚整理完成的 React 教程,包含了很多这样的故事桥段。我不禁笑了起来,这是入戏太深啊……

不过话说回来,这独臂画师跟 React 18 确实有很多相通之处。React 18 堪称 React 发展史上的一个里程碑,它的核心是所谓的“并发渲染”(Concurrent rendering)。


React 18核心:并发渲染(Concurrent rendering)

什么是并发渲染呢?这得从 React 18 之前版本的组件渲染机制说起。

React 渲染曾经是一个必须从头到尾完整执行的过程,一旦开始渲染就不能中断,要等到将界面效果呈现给用户以后才能开始下一轮。

这意味着什么呢?

我们知道 JavaScript 从本质上讲是单线程的,React 运行在浏览器的主线程之上,在这个单一的线程上还有很多代码排队执行,包括了对用户体验至关重要的用户输入处理、页面布局、动画等等。如果 React 的渲染代码执行时间太长,排在后面的其它代码便无法及时运行。所以,当渲染复杂组件时,用户界面常常会出现卡顿的现象。这好比要求我们的独臂画师必须完成一幅画以后才可以做其他事,停下来喝口水都不行。

不过,现在到了十八纪元,动作奇快的画师得以大显神威。

在 React 18 里,组件渲染过程变得可以暂停、可以从断点恢复、甚至可以丢弃一些过时中间结果,这样,不管组件有多复杂,其渲染过程也不会阻塞主线程。React 可以在一个组件上先画几笔,这时如果有更高优先级的任务(例如处理用户输入),或者因为某种原因需要等待(例如下载数据),React 就暂停这个组件的渲染,转而处理其他任务,在某个时刻再回过头来继续渲染原来的组件,因为切换的速度很快,从宏观上看来就是三头六臂、多个任务同时执行了!

(图片来源:Beebee老师)


并发渲染听起来很强大吧?那么作为开发者,我们怎么才能用到它的三头六臂呢?

事实上,并发渲染并非面向应用开发者的 API,它是 React 18 的底层工作机制,算是一种实现细节。不过,它是 React 18中(以及未来版本)很多新功能的基础。理解了并发渲染的工作原理,我们将会更加得心应手,所以我才在它上面花了这么长的篇幅。

下面挑两个 React 18 中最典型的新功能为你简略介绍一下,它们分别——Transition Suspense


Transition

Transition 相关 API 的目标是无缝支持不同配置的运行环境,旨在消除用户界面在慢速机器上的卡顿,而在高性能环境中又能充分利用计算资源、快速更新界面和显示更丰富的内容。

为了达到上述目标,React 18 需要我们帮助区分紧急和非紧急的界面更新。

所谓紧急更新,是指那些直接衔接用户交互的界面更新,例如显示键盘输入内容、鼠标点击反馈等等。如果此类界面更新没有得到及时处理,哪怕只是延迟了几百毫秒,用户就会感到很明显的卡顿。

而非紧急更新则是指那些即使是延迟处理也不会让人感到意外的界面更新,例如,根据下载的数据显示图表,即使慢个几秒问题也不大,此类更新也被称为 Transition。

正是因为并发渲染,React 可以“不紧不慢地”运行非紧急更新,而当用户输入到来时暂停手上的工作并立即处理紧急更新。这样,我们既在慢速机器上保证了界面的响应速度,又能在高性能环境中快速更新界面、显示更丰富的内容。类似的需求如果要“手工”来实现将会相当麻烦,效果还不一定理想。而在 React 18 里,我们只需要标记好非紧急更新,具体的更新速度和显示内容由 React 根据机器速度自动调节,对于开发者来说是完全透明的。

那么,怎么标记非紧急更新呢?

React 提供了一个 startTransition 函数(另外还有一个 useTransition Hook,用法类似,在此略去):

startTransition( () => { // 在此处放入非紧急更新,如 setData(...)。凡是不在此的更新均默认为紧急更新。})

如下是一个 Slider 组件的示例:

function FastSlider({ onChange }) { const [value, setValue] = useState(1); return ( <input type="range" value={value} onChange={(e) => { const v = e.target.valueAsNumber; setValue(v); // ==> 这是紧急更新,因为是对用户输入的反馈 startTransition(() => onChange(v)); // 这是非紧急更新,放到 startTransition 函数里让 React “慢慢”执行。 }} /> );}

所以,标记非紧急更新是很容易的,放到 startTransition 调用里就行了。React 将默认其它的更新为紧急更新。


Suspense

Suspense React 18 提供的一个组件,可以用来以声明式的方式定义进度信息。具体用法见如下代码:

function MyComponent() { return ( <Suspense fallback={<div>努力加载中...</div>}> <ComponentThatLoadsData /> </Suspense> )}

在上述代码里,当 ComponentThatLoadsData 开始下载数据时,对于该组件的渲染过程就会暂停(Suspend),Suspense 组件将接管并渲染 fallback 中的进度信息。

此时,用户将在浏览器中看到“努力加载中...”。等到数据下载完成,React 将继续渲染 ComponentThatLoadsData,显示最终结果。跟 Transition 类似,同样是并发渲染的三头六臂在这里起到了至关重要的作用。

你可能会问,用这种方式定义进度条到底有什么优势呢?以前用一个 loading state 加条件渲染的方式不是挺好吗?

这一点以后有时间我再撰文详述。

简言之,Suspense 将所有异步操作的这一部分逻辑抽象出来,把等待状态作为 JSX 里的“一等公民”,这样便于实现开发、设计工具支持,以及与设计师合作。毕竟,React 是以全面提高用户体验为目标的,与整个开发生态系统的协作是很重要的。

另外,React 18 中的 Suspense 在服务器端也有良好支持。同样是得益于并发渲染,服务器能够以流(stream)的方式为客户端提供渲染结果,这样就完美支持了包含异步操作的组件的 服务器端渲染(Server-side Rendering,SSR)。服务器能够先渲染组件的一部分,将包含进度信息的页面提供给客户端,等到暂停的组件准备就绪再提供剩余的渲染结果。


总结

React 18 以及画师的故事就讲到这里了。并发渲染是 React 前进的一大步,是 React 核心开发团队历经多年的研究、实验和开发的成果。我认为其必将对 React 以及整个前端开发领域的发展起到意义深远的作用。

不过,如果你还是 React 新手,是不是觉得有太多东西需要学了?什么组件、渲染,又加上 Transition、Suspense…… 告诉你一个好消息,你可以完全暂时不用管上面的代码和技术细节,记住独臂画师的六只手就够了。等到你掌握了 React 的基础知识,再回过头来一定会豁然开朗!

如果你喜欢这个关于画师的梦,我把《坐标 React 星:React 核心思维模型》这本书推荐给你。在书里,我用相同的手法以故事的形式讲解 React 的基础知识,让你在娱乐中学习。对了,画师在书里有出场哦!


 

下单即减50,快快扫码抢购吧!

当当423福利来啦!

KGHCJ9 (20元优惠码)

当当每满100-50 再叠加20元优惠码

实付100可用  花80元买原价200元的书


 

如果喜欢本文
欢迎 在看留言分享至朋友圈 三连

 热文推荐  





▼点击阅读原文,了解本书详情~

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存