从 React 谈 Web UI 开发

简介: 此前我在 Twitter 上这样表达过对 React 的理解,但是 Twitter 篇幅有限,所以在这篇文章里,我要做更详尽的阐述。

原文作者:UC 国际研发 Randy

微博:米斯特软的


image.png

此前我在 Twitter 上这样表达过对 React 的理解,但是 Twitter 篇幅有限,所以在这篇文章里,我要做更详尽的阐述。

我从前不喜欢 React, 是因为写 React 的 render function 不像写 template 一样方便,尤其是存在复杂的判断渲染的时候,Vue 的 template 一个 v-if 就搞定了。而在 React 里写,需要把这个判断写成 function, 然后条件判断 return 哪一个 view. 这是我最初对 React 的偏见所在之一。

然而经过自己的实践和思考,加上阅读一些文章,我发现以前的想法是错的。我在使用 React 的时候,没有做到 Thinking in React. 从而对 React 产生了不解和困惑。

有很多人把 React 当成框架来用,这是用不好 React 的根本原因。很少人认真思考 A JavaScript library for building User Interface 背后的含义,把 React 用得一团糟。

何谓 For Building User Interface? 意思就是,这个库仅仅是用于构建 UI 的,这是 React 本质要解决的问题。我甚至和很多人说,事实上 React 本身是不是 React 已经不重要了,重要的是我们写 UI 的思维。React 这个 library 本身仅仅是用来实现这个思维的手段。React 提供的,是优秀的 DOM diff 算法,和一套 Component system。换成代码来说,也就是:

image.png

这是 React building UI 的核心思想,所有的组件,就是接受 state, 返回一个 View. 这样看上去比较抽象,比如我们有一个 Clock 组件:

image.png

Clock 是一个 function, 接受一个 time 参数,返回的是一串 HTML String. 在程序里,我们可以给一个 Interval, 每秒传一个当前的 time, 得到一个新的 HTML String, 然后 apply 到某个 DOM 上。

image.png

这样的实现是能达到目的的,但是问题在于,每次 innerHTML 时,整个 #app 的 DOM 树会被重新渲染。

image.png

我们都知道,DOM 更新的花费是昂贵的。整个 DOM 树,实际上只是一个 span 在不断变化,所以我们需要 DOM diff 算法来得知到底哪一个 DOM 节点才需要被更新,从而节省开销:

image.png

在 React 里,把 props 传入,返回一个类似 HTML 的结构,然后 render 到指定的 DOM 节点上。这里 React 会算出哪个节点应该被更新:
image.png

我们这样手动去 setInterval 然后 render 未免有点傻,我们可以通过更改 state (也就是通常用到的 setState) 自动地让 React 随着 state 的改变而重新 render. 这里的 time 就是一个 state. 这叫做 Reactive.

Functional Programming 里有 Pure Function 的概念。Pure Function 之所以 Pure, 是因为不存在 side effect. 举个例子,我们写一个求和 function:

image.png

这个求和函数就是一个 pure function. 因为函数内部没有对 input 做任何改变,并且返回一个新的值。我传 1 和 1,得到的永远是 2.

Pure Function 的好处是利于维护和测试。要测试一个 Pure Function, 仅仅是传不同的值,预言对应的返回值。

现在回头看 React 的 Component, 也可以算是一个 Pure Function——接收不同的 props, 然后 render 对应的 View. 上面 Clock 的例子,props 和返回的 View 是映射关系。

光是 state => View 还不够,在构建 UI 的时候,我们希望 state 改变的时候,立即 rerender 整个 View, 也就是我们经常用到的 setState().

这样就很容易理解为什么我说 React 仅仅是实现构建 UI 思想的手段,因为构建 UI 的思想总结起来就是:

State 是 Reactive 的 (比如 React 的 setState)

state => View (依靠 DOM diff)

View 组成 Component

管理 state (依靠第三方的 state manager)

无论是 React 还是 Vue, 大抵都是这样的思想。Vue 1 还不完全是,Vue 2 就更接近了,只是后者写法既可以写得像 template, 又可以写直接写 vdom.

而开发者常常感到困难的地方实际上是上面的第 4 点——管理 state. 写 React 写得痛苦,大部分原因是用把 library 当成 framework 去用,把处理 state 的逻辑瞎写到 View 层中去,也就是所谓的 Dump Component.

改变 state 是 side effect, 我们应该把它从 View 层中分离出去。我多次提到,View 层真正要做的,仅仅是根据 state 返回对应的 View. state 的变化逻辑,应该在给 state manager 库去做,例如 Redux, Mobx. 下面我用 Mobx 作为例子:
640 (7).gif

https://jsbin.com/fumerup/edit?js,output

如果没有接触过 Mobx 不用慌张,只需要知道,Mobx 的 Observable 变化时,被 observer 包装的 React 组件会重新渲染。使用 state manager, 明显地分离了 View 和 side-effect:

image.png

测试这样的程序,首先为 side effect 的逻辑做测试,再为 View 做测试。View 的测试在这里就十分简单了,给他传一个 store 实例,借助 enzyme 之类的 testing utilities 预言不同的 action 得到的返回 View.

React 是 Reactive Programming 在 Web User Interface 上实现的手段,它只不过是一个库,提供了reactive render, component system 和降低开销的 DOM diff 算法. 把 React 换掉,只要不是手动操作 DOM, 其它的框架也不过大同小异。重要的是理解它背后的思想。说到底,前端开发在解决什么问题,用什么样的方式解决问题,在使用任何框架和库之前先把这两个问题思考明白,就不会认为前端难学了。

目录
相关文章
|
11月前
|
开发框架 前端开发 JavaScript
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发一
本文介绍了方舟开发框架(ArkUI)及其两种开发范式:基于ArkTS的声明式开发范式和类Web开发范式。ArkUI是用于构建HarmonyOS应用界面的UI框架,提供极简UI语法和基础设施。声明式开发范式使用ArkTS语言,以组件、动画和状态管理为核心,适合复杂团队协作;类Web开发范式采用HML、CSS、JavaScript三段式开发,适用于简单界面应用,贴近Web开发者习惯。文中还概述了两者的架构和基础能力,帮助开发者选择合适的范式进行高效开发。
356 15
|
11月前
|
编解码 前端开发 Java
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发三
本文介绍了基于声明式UI范式的图形绘制与动画效果实现方法,涵盖绘制图形、添加动画效果及常见组件说明三部分内容。在绘制图形部分,详细讲解了如何通过Circle组件为食物成分表添加圆形标签,以及使用Path组件结合SVG命令绘制自定义图形(如应用Logo)。动画效果部分则展示了如何利用animateTo实现闪屏动画,包括渐出、放大效果,并设置页面跳转;同时介绍了页面间共享元素转场动画的实现方式。最后,文章列举了声明式开发范式中的各类组件及其功能,帮助开发者快速上手构建复杂交互页面。
377 11
|
7月前
|
存储 开发者 容器
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
本文介绍了ArkTS语言中的Class类、泛型、接口、模块化、自定义组件及状态管理等核心概念,并结合代码示例讲解了对象属性、构造方法、继承、静态成员、访问修饰符等内容,同时涵盖了路由管理、生命周期和Stage模型等应用开发关键知识点。
512 1
鸿蒙 HarmonyOS NEXT星河版APP应用开发-ArkTS面向对象及组件化UI开发使用实例
|
10月前
|
JavaScript 前端开发 UED
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发四
本文介绍了Web组件开发与性能优化的相关内容。在Web组件开发部分,涵盖创建组件、设置样式与属性、添加事件和方法以及场景示例,如动态播放视频。性能提升方面,推荐使用数据懒加载、条件渲染替代显隐控制、Column/Row替代Flex、设置List组件宽高及调整cachedCount减少滑动白块等方法,以优化应用性能与用户体验。
333 56
|
10月前
|
编解码 UED 开发者
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发之常见布局
本文主要介绍了自适应布局与响应式布局的相关内容。自适应布局部分涵盖线性布局、层叠布局、弹性布局和网格布局,详细说明了各布局的特性及使用方法,例如线性布局中的排列、拉伸与缩放,弹性布局的方向、换行与对齐方式等。响应式布局则重点讲解了栅格系统和媒体查询,阐述如何通过栅格组件和媒体查询条件实现不同设备上的适配效果。这些技术帮助开发者灵活应对多尺寸屏幕的设计需求,提升用户体验。
483 55
|
前端开发 安全 开发工具
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
911 90
【11】flutter进行了聊天页面的开发-增加了即时通讯聊天的整体页面和组件-切换-朋友-陌生人-vip开通详细页面-即时通讯sdk准备-直播sdk准备-即时通讯有无UI集成的区别介绍-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
11月前
|
运维 前端开发 数据可视化
【CodeBuddy】挑战一句话开发一个完整项目之:React表单验证系统
本文分享了一个基于React 19构建的用户注册表单系统,采用模块化CSS和状态驱动视图更新,实现实时校验、错误提示与提交反馈等功能。核心亮点包括验证规则引擎(如密码复杂度校验)、交互反馈体系(输入框警示、按钮禁用)及加载动画优化。通过函数式更新确保状态同步,正则表达式实现多条件验证,CSS伪元素打造流畅体验。代码结构清晰,可扩展性强,适合作为React表单开发模板。文末附CodeBuddy免费下载链接,助力高效开发!
266 1
【CodeBuddy】挑战一句话开发一个完整项目之:React表单验证系统
|
11月前
|
存储 开发框架 API
【HarmonyOS Next之旅】基于ArkTS开发(二) -> UI开发二
本文详细介绍了基于声明式UI开发的健康饮食应用的设计与实现过程。内容涵盖从基础环境搭建到复杂功能实现的全流程,包括创建简单视图、构建布局(如Stack、Flex)、数据模型设计、列表与网格布局构建,以及页面跳转和数据传递等核心功能。 本文通过实际案例深入浅出地解析了声明式UI开发的关键技术和最佳实践,为开发者提供了宝贵的参考。
400 14
|
JavaScript 前端开发 API
如何在React.js中使用Shadcn/UI
学习如何在React.js中使用Shadcn/UI构建轻量且可定制的现代化界面。Shadcn/UI为React.js打造,提供核心组件和Tailwind CSS支持,帮助你创建独特的UI,避免大型框架的臃肿。本文介绍安装、配置及与Apipost集成的方法,适合希望提升React.js项目的开发者。通过定制主题和优化性能,你可以高效地开发出功能强大的应用。
1103 59
|
10月前
|
JavaScript 前端开发 开发者
09.HarmonyOS Next数据驱动UI开发:ForEach与动态渲染完全指南(上)
在现代前端开发中,数据驱动UI已成为主流开发范式。HarmonyOS Next的ArkTS语言和声明式UI框架完美支持这一理念,使开发者能够以更高效、更直观的方式构建复杂应用。
274 1