本篇主要的介绍了关于reactjs出现的一些问题,指出了现在用reactjs的一些弊端,有兴趣的同学可以进来看看这篇文章
背景介绍
去年 4 月,我第一次在某个客户的项目中接触到ReactJS 。
我发现ReactJS要比我以前用过的AngularJS简单很多,它提供了响应式的数据绑定功能,把数据映射到网页上,使我可以轻松实现交互简单的网站。
然而,随着我越来越深入的使用ReactJS,我发现用ReactJS编写交互复杂的网页很困难。 我希望有一种方式,能够像ReactJS一样简单解决简单问题。此外,还要能简单解决复杂问题。
于是我把ReactJS用Scala重新写了一个。代码量从近三万行降到了一千多行。
用这个框架实现的TodoMVC应用,只用了154行代码。而用ReactJS实现相同功能的TodoMVC,需要488行代码。
下图是用Binding.scala实现的TodoMVC应用。
这个框架就是Binding.scala。
问题一:ReactJS组件难以在复杂交互页面中复用
ReactJS中的最小复用单位是组件。ReactJS的组件比AngularJS的Controller和View 要轻量些。 每个组件只需要前端开发者提供一个 render
函数,把 props
和 state
映射成网页元素。
这样的轻量级组件在渲染简单静态页面时很好用, 但是如果页面有交互,就必须在组件间传递回调函数来处理事件。
我将在《More than React(二)组件对复用性有害?》中用原生DHTML API、ReactJS和Binding.scala实现同一个需要复用的页面,介绍Binding.scala如何简单实现、简单复用复杂的交互逻辑。
问题二:ReactJS的虚拟DOM 算法又慢又不准
ReactJS的页面渲染算法是虚拟DOM差量算法。
开发者需要提供 render
函数,根据 props
和 state
生成虚拟
DOM。 然后 ReactJS 框架根据 render
返回的虚拟 DOM 创建相同结构的真实 DOM.
每当 state
更改时,ReacJS 框架重新调用 render
函数,获取新的虚拟
DOM 。 然后,框架会比较上次生成的虚拟 DOM 和新的虚拟 DOM 有哪些差异,然后把差异应用到真实DOM上。
这样做有两大缺点:
-
<li>
每次 state
更改,render
函数都要生成完整的虚拟
DOM. 哪怕 state
改动很小,render
函数也会完整计算一遍。如果 render
函数很复杂,这个过程就白白浪费了很多计算资源。
ReactJS框架比较虚拟DOM差异的过程,既慢又容易出错。比如,假如你想要在某个 <ul>
列表的顶部插入一项 <li>
,那么ReactJS框架会误以为你修改了 <ul>
的每一项 <li>
,然后在尾部插入了一个 <li>
。
这是因为 ReactJS收到的新旧两个虚拟DOM之间相互独立,ReactJS并不知道数据源发生了什么操作,只能根据新旧两个虚拟DOM来猜测需要执行的操作。 自动的猜测算法既不准又慢,必须要前端开发者手动提供 key
属性、shouldComponentUpdate
方法、componentDidUpdate
方法或者 componentWillUpdate
等方法才能帮助
ReactJS 框架猜对。
我将在《More than React(三)虚拟DOM已死?》中比较ReactJS、AngularJS和Binding.scala渲染机制,介绍简单性能高的Binding.scala精确数据绑定机制。
问题三:ReactJS的HTML模板功能既不完备、也不健壮
ReactJS支持用JSX编写HTML模板。
理论上,前端工程师只要把静态HTML原型复制到JSX源文件中, 增加一些变量替换代码, 就能改造成动态页面。 理论上这种做法要比Cycle.js、Widok、ScalaTags等框架更适合复用设计师提供的HTML原型。
不幸的是,ReactJS对HTML的支持残缺不全。开发者必须手动把class
和for
属性替换成className
和htmlFor
,还要把内联的style
样式从CSS语法改成JSON语法,代码才能运行。
这种开发方式下,前端工程师虽然可以把HTML原型复制粘贴到代码中,但还需要大量改造才能实际运行。 比Cycle.js、Widok、或者、ScalaTags省不了太多事。
除此之外,ReactJS还提供了propTypes
机制校验虚拟DOM的合法性。 然而,这一机制也漏洞百出。 即使指定了propTypes
,ReactJS也不能在编译前提前发现错误。只有测试覆盖率很高的项目时才能在每个组件使用其他组件时进行校验。
即使测试覆盖率很高,propTypes
仍旧不能检测出拼错的属性名,如果你把onClick
写成了onclick
,
ReactJS就不会报错,往往导致开发者额外花费大量时间排查一个很简单的bug。(想看更多就到PHP中文网React参考手册栏目中学习)
我将在《More than React(四)HTML也可以编译?》中比较ReactJS和Binding.scala的HTML模板,介绍Binding.scala如何在完整支持XHTML语法的同时静态检查语法错误和语义错误。
问题四:ReactJS与服务器通信时需要复杂的异步编程
ReactJS从服务器加载数据时的架构可以看成MVVM(Model–View–ViewModel)模式。 前端工程师需要编写一个数据库访问层作为Model,把ReactJS的state
当做ViewModel,而render
当做View。
Model负责访问数据库并把数据设置到state
(即View Model)上,可以用Promise和fetch API实现。 然后,render
,即View,负责把View
Model渲染到页面上。
在这整套流程中,前端程序员需要编写大量闭包组成的异步流程, 设置、访问状态的代码五零四散, 一不小心就会bug丛生,就算小心翼翼的处理各种异步事件,也会导致程序变得复杂,既难调试,又难维护。
我将在《More than React(五)为什么别用异步编程?》中比较ReactJS和Binding.scala的数据同步模型,介绍Binding.scala如何自动同步服务器数据,避免手动异步编程。
结论
尽管Binding.scala初看上去很像ReactJS, 但隐藏在Binding.scala背后的机制更简单、更通用,与ReactJS和Widok截然不同。
所以,通过简化概念,Binding.scala灵活性更强,能用通用的方式解决ReactJS解决不了的复杂问题。
比如,除了上述四个方面以外,ReactJS的状态管理也是老大难问题,如果引入Redux或者react-router这样的第三方库来处理状态,会导致架构变复杂,分层变多,代码绕来绕去。而Binding.scala可以用和页面渲染一样的数据绑定机制描述复杂的状态,不需要任何第三方库,就能提供服务器通信、状态管理和网址分发的功能。
以下表格中列出了上述Binding.scala和ReactJS的功能差异:
Binding.scala | ReactJS | ||
---|---|---|---|
Binding.scala | ReactJS | ||
复用性 | 最小复用单位 | 方法 | 组件 |
复用难度 | 不论交互内容还是静态内容都容易复用 | 容易复用静态内容组件,但难以复用交互组件 | |
页面渲染算法 | 算法 | 精确的数据绑定 | 虚拟 DOM |
性能 | 高 | 低 | |
正确性 | 自动保证正确性 | 需要开发者手动设置 key 属性,不然复杂的页面会错乱。 |
|
HTML 模板 | 语法 | Scala XML 字面量 | JSX |
是否支持 HTML 或 XHTML 语法 | 完整支持 XHTML | 残缺支持。正常的 XHTML 无法编译。开发者必须手动把 class 和 for 属性替换成 className 和 htmlFor ,还要把内联的 style 样式从
CSS 语法改成 JSON 语法。 |
|
如何校验模板语法 | 自动编译时校验 | 运行时通过 propTypes 校验但无法检测简单的拼写错误。 |
|
服务器通讯 | 机制 | 自动远程数据绑定 | MVVM + 异步编程 |
实现难度 | 简单 | 复杂 | |
其他 | 如何分派网址或者锚点链接 | 支持把网址当成普通的绑定变量来用,无需第三方库。 | 不支持,需要第三方库 react-router |
功能完备性 | 完整的前端开发解决方案 | 本身只包含视图部分功能。需要额外掌握 react-router 、 Redux 等第三方库才能实现完整的前端项目。 | |
学习曲线 | API 简单,对没用过 Scala 的人来说也很好懂 | 上手快。但功能太弱导致后期学习第三方库时曲线陡峭。 |
两个多月前,我在Scala.js的论坛发布Binding.scala时,当时Scala.js社区最流行的响应式前端编程框架是Widok。Tim Nieradzik是Widok的作者。他在看到我发布的框架后,称赞这个框架是Scala.js社区最有前途的 HTML 5渲染框架。
他是对的,两个月后,现在Binding.scala已经成为Scala.js社区最流行的响应式前端编程框架。
Awesome Scala网站对比了Scala的响应式前端编程框架,Binding.scala的活跃程度和流行度都比Udash、Widok等其他框架要高。
本篇文章到这就结束了(想看更多就到PHP中文网React使用手册栏目中学习),有问题的可以在下方留言提问。
以上是ReactJS的问题有哪些?reactjs问题的总结的详细内容。更多信息请关注PHP中文网其他相关文章!

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

从C/C 转向JavaScript需要适应动态类型、垃圾回收和异步编程等特点。1)C/C 是静态类型语言,需手动管理内存,而JavaScript是动态类型,垃圾回收自动处理。2)C/C 需编译成机器码,JavaScript则为解释型语言。3)JavaScript引入闭包、原型链和Promise等概念,增强了灵活性和异步编程能力。

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3汉化版
中文版,非常好用

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Dreamweaver CS6
视觉化网页开发工具

mPDF
mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

禅工作室 13.0.1
功能强大的PHP集成开发环境