React实战

978-7-115-53192-6
作者: [美]马克·蒂伦斯·托马斯(Mark Tielens Thomas)
译者: 任发科陈伟蒋峰邱巍
编辑: 杨海玲

图书目录:

详情

《React实战》涵盖了构建React应用所涉及的概念和API,全书共13章,分为3个部分,从React的核心思想和关键点讲起,并随着进展涉及更具体和高级的主题。首先介绍React的核心思想,探讨了React的一些关键点,展示React如何适应使用者的开发过程;然后开始深入React,描述数据如何在React中流动,介绍组件生命周期API,开始构建Letters Social示例项目,处理表单以及路由的关键部分;最后将注意力专门放在把应用转换到使用Redux,介绍Redux状态管理方案,探索服务器端渲染,并简要地介绍React Native项目。 本书结构清晰,内容由浅入深,适合任何对React感兴趣,想学习React的读者,也适合前端开发人群。

图书摘要

版权信息

书名:React实战

ISBN:978-7-115-53192-6

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

著    [美]马克•蒂伦斯•托马斯(Mark Tielens Thomas)

译    任发科  陈 伟  蒋 峰  邱 巍

责任编辑 杨海玲

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


Original English language edition, entitled React in Action by Mark Tielens Thomas published by Manning Publications Co., 209 Bruce Park Avenue, Greenwich, CT 06830. Copyright © 2018 by Manning Publications Co.

Simplified Chinese-language edition copyright © 2020 by Posts & Telecom Press. All rights reserved.

本书中文简体字版由Manning Publications Co.授权人民邮电出版社独家出版。未经出版者书面许可,不得以任何方式复制或抄袭本书内容。

版权所有,侵权必究。


本书涵盖了构建React应用所涉及的概念和API,全书共13章,分为3个部分,从React的核心思想和关键点讲起,并随着进展涉及更具体和高级的主题。首先介绍React的核心思想,探讨了React的一些关键点,展示React如何适应使用者的开发过程;然后开始深入React,描述数据如何在React中流动,介绍组件生命周期API,开始构建Letters Social示例项目,处理表单以及路由的关键部分;最后将注意力专门放在把应用转换到使用Redux,介绍Redux状态管理方案,探索服务器端渲染,并简要地介绍React Native项目。

本书结构清晰,内容由浅入深,适合任何对React感兴趣,想学习React的读者,也适合前端开发人群。


任发科 火币网高级研发总监,曾任职亚马逊、唯品会等多家互联网公司,担任研发和技术管理工作,有丰富的软件架构、开发和管理经验。个人长期从事和关注高效研发组织的构建和管理,并有丰富的团队管理实践。近年来主要关注和从事研发效能、DevOps体系的建立,目前从事稳定性工程的相关工作。

陈伟 哗啦啦前端架构师,曾在唯品会、火币等公司任前端工程师和前端架构师。对JavaScript语言以及Node.js、Vue、React等前端框架有深入理解,并在前端组件化方向有深入的工程化研究。目前致力于可视化的页面编辑器的设计和开发,赋能产品与前端,提升公司开发效率。

蒋峰 火币网资深前端工程师,曾就职于国家农业信息化中心、阿里健康、融数金服等从事软件研发、基础架构等工作,目前主要负责火币网前端相关产品研发管理工作。早年间致力于微软.NET框架研发,近年来专注于前端研发体系架构,有大量的C#、Node.js和JavaScript项目开发经验,对Electron跨平台应用有极大的兴趣与研究。目前正在积极推进企业内中后台微前端应用方案的验证与实施。

邱巍 现就职于哗啦啦研发中心,曾就职于作业盒子、融数金服、火币网等从事软件研发工作,目前主要负责数据可视化基础组件研发。对图表绘制、图表交互、数据建模与分析等相关内容有极大兴趣。目前致力于提供展现更准确、分析更高效的数据可视化工具研发。


当我最初开始学习和使用React的时候,JavaScript社区刚开始从一个快速创新和颠覆的周期安定下来。React正变得很流行,而JavaScript社区在诸多方面仍旧像《狂野西部》一样。我对React这一技术感到兴奋,因为它展现出真正的希望。心智模型似乎很可靠,组件让构建UI变得更简单,API灵活且富于表达性,整个项目看起来“恰到好处”。暂且不提API外观、可用性和理论基础,还有一个事实就是,对我来说React真的很酷,而且我喜欢用它。

自那时起,已经发生了很多变化——与此同时,有些方面并没有太多改变。React的基本概念和API基本保持不变,但已经涌现和演化出一套知识和最佳实践,而且有更多的人在使用它。一个由库和相关技术组成的开源生态正蓬勃发展。会议、聚会和社区或多或少都会涉及React。React核心团队在React的版本16重写了React内部架构,它既保持了向后兼容又为未来的大量创新铺平了道路。所有这些“没有太大变化的改变”都指向我所认为的React的最大优势之一:维持稳定性和创新之间的紧张关系,在不让人望尘莫及的情况下推动采用。

鉴于以上原因,React持续占据技术主导地位而且只会变得更加流行。许多大公司、无数的创业公司以及其他各类公司都在以某种方式使用它。许多目前没有使用React的公司正尝试切换到React来将它们的前端应用现代化。

React的流行发展并未拘囿于Web——它还向其他平台进军。React Native,React在移动平台的港口,也成为一项重大创新。它展示了React的“一次学习,到处编写”的方法。将React作为平台的想法意味着不要局限于将其用于基于浏览器的应用。

让我们忘记对React的大肆宣传并聚焦于本书应该为读者做什么。我对本书的主要期望是它能帮助读者有效地理解和使用React,它甚至可以让读者更好地全面构建用户界面,即使一点点。我无意参与流行词驱动的开发或推动读者转向“魔法”技术,相反,我将赌注压在健壮的心智模型以及结合实际例子的深入理解会让读者用React做不可思议的事情,无论自己做还是和别人一起。


Mark Tielens Thomas是一位全栈软件工程师和作者。他和他妻子在南加州生活和工作。Mark喜欢解决大规模工程问题并带领团队交付高影响力、高价值的解决方案。他深爱上好的咖啡、很多书、快速的API以及漂亮的系统。他为Manning出版社写作并在个人博客上创作。


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

本书提供本书源代码,要获得这一配套资源,请在异步社区本书页面中点击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑。

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,点击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线投稿(直接访问www.epubit.com/selfpublish/ submission即可)。

如果您来自学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。

异步社区

微信服务号


别等到事情完美才与他人分享。尽早展示,频繁展示。当我们到达时它会变漂亮,但沿途并非如此。

—— Ed Catmull,《创新公司:皮克斯的启示》

有价值的努力很少是独立完成的,但许多情况下,成功却完全归于一个人或几个人,这种将功劳归于少数人的方式掩盖了致力于最终目的的更大的贡献者网络。那些声称“独自完成”的人常常没有意识到其他人帮助他们的方式,无论通过示范帮助他们还是通过指示帮助他们。另外,他们也没有意识到在社区中工作的力量会推动其获得更为难以企及的成功和卓越。独自工作意味着受限于个人(并且只有个人)能做什么,合作却可以通过让我们敞开心胸接受谦虚、新想法、不同视角和无价的反馈来提供一条通往卓越的道路。

我不会愚蠢到认为这本书是我一个人写的,哪怕这种想法只有一秒。我的手指敲击了键盘,我的名字出现在封面上,但那并不意味着这是个人秀。不,就像我生命中所有让我感恩的东西,这本书是由一群聪明、谦逊和有爱心的人所组成的丰富多彩的社区的结果,他们愿意对我付出耐心、善意,有时还有严苛。

首先,我要感谢我的妻子Haley。她是我的开心果、我最好的朋友、我的创作伙伴。她已经为这本书忍受了很长时间。深夜,更多深夜,没完没了地讨论这本书。她这位才华横溢的优秀作家在我遇到写作障碍时帮助我,在我感觉成书无望时鼓励我。她始终如一地爱和祈祷,总是在我低谷时抚慰我,在我自我怀疑时质疑我,在欢乐时与我一同分享。她在整个过程中一直非常出色,我迫不及待地想要报答她,在她未来想写的许多书上帮助她。我会一直无限地感激她。

我还要感谢在这个过程中支持我的我生命中的其他人。我真诚地感谢拥有这样一个美妙的家庭。我妈我爸—Annmarie和Mitchell—在我编写本书的过程中(以及我整个生命中)一直鼓励我,他们还承诺完整地读这本书,虽然我不会强迫他们这么做。我两个哥哥—David和Peter—也一直支持和鼓励我,他们没有承诺读这本书,但我会在接下来的一年里(或者不管多长时间)大声读给他们听。我的那些教友、玩伴和工友也一直非常热心地帮助我,他们帮了很大的忙,一直通过追问“写完了没?”来激励我,而且容忍我对React的解释。我还要感谢我的教授,特别是Diana Pavlac Glyer博士,她教我如何思考和写作。

Manning出版社的工作人员在我写作的过程中提供了很多帮助。我要特别感谢Marina Michaels(开发编辑)、Nickie Bruckner(技术开发编辑)和German Frigerio(技术检验员),他们花了无数小时阅读和帮助我写作。没有他们就不会有这本书。我还要感谢Brian Sawyer联系我写这本书以及Marjan Bace最初给我写这本书的机会。Manning出版社的每个人都致力于帮助世界各地的人们以有效的方式学习有影响力的重要技能和概念,我坚信并很高兴能帮助进一步履行Manning出版社的教育使命。


这是一本关于React的书,React是构建Web用户界面的库。本书涵盖了构建React应用所涉及的概念和API。读者将会在阅读本书的过程中使用React构建一个示例社交网络应用。这个应用将涉及各种主题,从添加动态数据到服务器端渲染。

本书是为那些想要学习React的人写的,无论是软件工程师、工程副总裁、首席技术官(CTO)、设计师、工程经理、大学或编程训练营的学生,还是其他对React感兴趣的人,都适合阅读。读者可以根据自己的需要,将注意力集中在本书的不同部分。我在本书的第一部分先介绍React,并随着学习进展涉及更具体和高级的主题。

如果读者对JavaScript有一定了解,会有更好的阅读体验。本书大量使用了JavaScript,但不是一本关于JavaScript的书。我不会涉及JavaScript的基本概念,但如果它们与React的讨论相关,我会稍加涉及。如果读者对JavaScript基本熟练并理解如何通过JavaScript进行异步编程,那么应该能够通读示例。

本书还假定读者已经从技术角度了解构建前端Web应用的一些基础知识——了解基本浏览器API会很有帮助。我们将使用Fetch API这样的东西进行网络请求、设置和读取cookie,处理用户事件(按键、点击等),我们还会与库打交道(尽管不是非常多)。熟悉现代前端应用的基本知识会帮助读者最大限度地利用本书。

幸运的是,我已经将所有围绕工具和构建过程(这也是构建现代Web应用的必要部分)的复杂性抽象出来。项目的源代码包含了所有依赖和构建工具,因此读者应该不必为了阅读本书而去理解Webpack和Babel是如何工作的。总而言之,读者应该至少基本熟练JavaScript和一些前端Web应用概念才能充分享受阅读本书的乐趣。

本书共13章,分为3个部分。

第一部分介绍React。第1章先介绍React的核心思想。它探讨React的一些关键点,展示React如何适应使用者的开发过程,看看React能做什么以及不能做什么。第2章是“展示代码”的章。我将带领读者钻研React API并用React组件构建一个示例评论框。

第二部分开始深入React。读者将在第3章看到数据如何在React中流动,了解组件生命周期API,并在第4章开始构建Letters Social示例项目。这个项目将贯穿本书的剩余部分。第4章会介绍从应用源代码设置项目,并解释本书的剩余部分如何使用它。第5章到第9章更深入介绍React。第5章涉及表单处理,并教会读者用另一种方式来处理React中的数据和数据流。第6章延续相同的思路并基于第5章的工作成果构建更复杂的React地图展示组件。第7章和第8章处理路由这一几乎所有现代前端应用的关键部分。读者将从头构建一个路由器并设置应用处理多个页面。第8章继续介绍路由,并与Firebase平台进行集成,以便能够对用户进行身份验证。最后,第9章介绍React应用和组件的测试。

第三部分涉及更高级的React主题,并将注意力专门放在把应用转换为使用Redux。第10章和第11章介绍Redux这个状态管理方案。将应用转换为使用Redux之后,我们将在第12章探索服务器端渲染。这一章还涉及将自建路由器转换为React Router。第13章会简要地介绍React Native,另一个React项目,这一项目允许开发人员为移动设备(iOS和Android)编写JavaScript React应用。

本书使用两组主要的源代码。对于前两章,读者将处理项目代码库之外的代码。读者将能够在CodeSandbox这个在线代码平台上运行这些代码示例。该平台负责打包代码并实时运行,因此读者不必操心搭建构建过程。

第4章将搭建项目源代码。这些源代码可以从出版社网站及以React in Action命名的本书GitHub仓库上下载,项目最终结果运行在https://social.react.sh。每章或者每几章有自己的Git分支,读者可以轻松地切换到后续章或者跟随本书的项目进程。所有源代码都在GitHub上,欢迎读者随时在GitHub上提问。

应用的JavaScript都使用Prettier进行格式化,用最新的ECMAScript规范(本书编写时是ES2017)编写。Prettier使用该规范中的概念、语法和方法。项目包含了ESLint配置,但如果读者想修改它以适应自己的需要,请随意。

本书没有严格的硬件要求。读者可以自由使用任何类型的计算机(物理机或是像Cloud9这样的虚拟机提供者),但我不会解决开发环境差异所造成的不一致问题。如果问题出现在单独的包中,这些包的代码库或Stack Overflow是寻求帮助的最好选择。

至于软件,下面是一些要求和建议。


本书封面插图的标题为The Capitan Pasha, Derya Bey, admiral of the Turkish navy。Pasha上尉是奥斯曼帝国海军的最高指挥官。这幅画取自奥斯曼帝国的套装合集,由伦敦老邦德街(Old Bond Street)的William Miller在1802年1月1日出版。该合集的标题页已遗失,我们无法追查到它的日期。书的目录用英语和法语标识出这些图,每幅插图上都有两位创作这幅插画的艺术家的名字,如果他们发现自己的艺术品出现在200年后的计算机书籍的封面上,毫无疑问,他们一定会感到吃惊。

Manning出版社的一位编辑在麦哈顿西26街“Garage”的古董跳蚤市场购买了这个合集。卖家是一位驻土耳其安卡拉的美国人,交易发生时他正在收拾摊位。Manning出版社的编辑没有带够购买所需的大量现金,而信用卡和支票都被礼貌地拒绝了。由于卖家当晚要飞回安卡拉,情况变得越来越没有希望。怎么办?结果是达成了以握手保证的老式口头协议。卖家简单地建议把钱汇给他,而编辑走时带着一张写有银行信息的纸以及夹在腋下的一组画。不用说,我们第二天就转了钱,我们仍对这位不知名的人对我们中的一员保有的信任心存感激,并对他印象深刻。这幅画让人回忆起发生在很久之前的事情。

我们在Manning出版社赞美基于两个世纪前丰富多彩的地域生活的书籍封面的创作性、首创性,以及计算机业务的乐趣,这些生活从这些图片中恢复生机。


如果你近两年开发过前端JavaScript应用,可能已经听说过React了。即使你刚刚接触用户界面构建,可能也已经听说过它了。就算这是第一次听说React,你应该也已经接触过React:有很多非常流行的应用使用了React。如果你使用过Facebook,观看过Netflix,或者在Khan学院学习过计算机科学,那就已经用过React创建的应用了。

React是一个用于构建用户界面的库。它由Facebook的工程师创建,自其发布以来就在JavaScript社区掀起了热潮。过去几年中,它日益普及,成为很多团队和工程师构建动态用户界面的首选工具。实际上,React的API、思维模型和活跃的社区结合在一起,已经将React的开发带到了其他平台,包括移动端甚至虚拟现实。

本书将探索React,看看它成为如此成功且有用的开源项目原因何在。第一部分将从头开始学习React的基础知识。由于构建健壮的JavaScript UI应用所涉及的工具可能非常复杂,我们将避免陷入这些工具之中,并专注于学习React API的方方面面。我们也会避免“魔法”,并致力于建立对React及其工作原理的具体理解。

第1章将从较高层次学习React。我们将介绍一些重要思想,如组件、虚拟DOM,以及React中的一些权衡和取舍。第2章会大致过一遍React的API,并通过创建一个简单的评论框组件来着手实践React。


本章主要内容

如果你在技术行业中做Web工程师,可能听说过React。有可能是从网上听到的,如Twitter或Reddit。可能是朋友或同事提到了它,又或者是在一次聚会上听到了有关它的讨论。无论是在哪儿,我敢打赌,听到的要么是赞美要么是怀疑。大部分人对React这样的技术有着鲜明的观点。有影响力的技术往往会产生这样的效应。这些技术流行起来并触及更广泛的受众前,最初通常只会有很小一部分人“了解它”。React就是以这种方式开始的,但现在它在Web工程全球极受欢迎并被广泛使用。它的流行并非没有原因:它不但提供了很多东西而且能够重新激发、更新甚至转变你思考和构建用户界面的方式。

React是一个用于构建跨平台用户界面的JavaScript库。React给予开发者强大的思维模型并帮助开发者以声明式和组件驱动的方式构建用户界面。这是React最宽泛和最简短的定义,我们将在本书中详细解释这些观点。

在广阔的Web工程领域中,React位于何处?React经常在Vue、Preact、Angular、Ember、Webpack、Redux以及其他知名JavaScript库和框架的相同领域中被谈及。React通常是前端应用的主要部分并且与我们刚刚提到的其他库和框架拥有类似的特性。事实上,相比以往,许多流行的前端技术现在都与React莫名地类似。曾几何时,React的做法是新颖的,而其他技术自那时就被React的组件驱动、声明式做法所影响。React持续保持“重新思考已建立的最佳实践”的精神,其主要目标是为开发人员提供一种富有表现力的思维模型和一种高性能的技术来构建UI应用。

是什么使得React的思维模型如此强大?这是因为它利用了计算机科学和软件工程技术的深层领域。React的思维模型广泛使用了函数式和面向对象编程的概念,并重点将组件作为构建的主要单元。React应用中,开发人员可以用组件创建用户界面。React的渲染系统管理着这些组件并保持着应用视图的同步。组件通常对应着用户界面的一个部分,如日期选择器、页头、导航等,但它们也可以负责客户端路由、数据格式化、样式以及客户端应用的其他职能。

React中的组件应该易于理解并很容易与其他React组件集成;它们遵循可预测的生命周期,能够维护自己的内部状态,并与“常规Javascript”兼容。我们将在本书的后续部分深入探讨这些理念,但目前我们可以先从较高层次来看看它们。图1-1给出了React应用的主要“成分”的概览。

图1-1 React能够用组件创建用户界面。组件维护了自身的状态,使用“vanilla”JavaScript[1]编写与
运行,并从React继承了许多有用的接口。大部分React应用是为基于浏览器的环境编写的,
但也可以用于iOS和Android这样的原生环境。关于React Native的更多信息,查阅
Nader Dabit的React Native in Action,也可以从Manning出版社网站获取

让我们大致了解一下每个部分。

本书中我们会花大量的时间来探索React的方方面面,但开始之前可能会有一些问题。React真的有所帮助吗?还有谁在使用React?权衡使用或不使用React的依据有哪些?在采用一项新技术之前,这些都是希望得到回答的重要问题。

本书面向那些正致力于构建用户界面或对其感兴趣的人。实际上,本书是写给任何对React感兴趣的人的,即使他们的工作并不涉及UI工程。如果有一些使用JavaScript构建前端应用的经验,读者将从本书获得最大收益。

只要了解JavaScript的基础并有一些构建Web应用的经验,就能学会如何用React构建应用。本书中不会涉及JavaScript的基础知识。诸如原型继承、ES2015以及之后版本的代码、强制类型转换、语法、关键字、类似async/await的异步编程模式和其他基础主题都不在本书的范围内。我只会稍微涉及一些与React特别相关的内容,但我不会将JavaScript作为一门语言来深入研究。

这并不意味着如果不了解JavaScript就不能学习React或者无法从本书中学到任何东西。但如果你学过JavaScript,那么将有更多收获。没有JavaScript的基础知识就贸然向前冲会让事情变得更加困难。可能会遇到这样的情况——对一些人来说事情看起来就像“魔法”——事情可以奏效,但这些人却不理解为什么。这通常会伤害开发者而不是帮助他们,所以……最后的警告是:在学习React之前要先熟悉JavaScript的基础知识。JavaScript是一种富有表现力和灵活性的语言,你会爱上它的!

你可能已经很熟悉JavaScript,甚至之前已经尝试过React。考虑到React已经变得如此流行,这并不会让人太过惊讶。如果就是这样,那么你将能够更深入地理解React的一些核心概念。但是,如果你已经使用了一段时间React,我可能不会涉及你可能正在寻找的非常特定的主题。对于这类读者,可以看看其他React相关的书籍,如React Native in Action

你可能不属于(上述)任何一类,只想对React有一个高层概览,那么本书对你同样适用。你将了解React的基本概念,并接触用React编写的示例应用。你将通过实践了解构建React应用的基础知识,以及它如何适用于你的团队或下一个项目。

如果过去几年你已在前端应用上做了大量工作,那么就不会对这一事实感到惊讶——围绕应用的工具已经成为开发过程中与框架和库本身同样重要的一部分。今天,开发人员可能会在应用中使用Webpack、Babel或其他工具。这些工具和其他工具在本书中占据什么位置?你需要知道哪些东西呢?

你并不需要精通Webpack、Babel或其他工具就能阅读这本书。我创建的示例应用使用了为数不多的重要工具,你可以通过阅读示例应用中的配置代码来了解这些工具,但我在本书中不会深入介绍这些工具。工具变化的速度很快,更重要的是,深入讨论这些主题将远远超出本书的范围。当工具与我们的讨论相关时,我一定会提示,但除此以外我将避免涉及它。

我还觉得,学习像React这样的新技术时,工具可能会让人分心。你已经试着让自己的思维转换到一套新的概念和范例,为什么还要学习复杂的工具来扰乱它呢?这就是为什么第2章要先着重学习“原生”React,然后再介绍那些需要构建工具的特性,如JSX和JavaScript语言的一些特性。你需要熟悉的一个工具是npm。npm是JavaScript的包管理工具,我们将使用它安装项目依赖并在命令行运行项目命令。你可能对npm已经很熟悉了,但如果没有,不要因此而放弃阅读本书。你只需要最基本的命令行和npm技能就能继续。

当涉及开源软件时,谁使用它(以及谁不使用它)不只是关乎流行的问题。它影响使用该技术的体验(包括支持、文档和安全修复的可用性)、社区的创新水平,以及某个工具的潜在生命周期。那些有着活跃社区、健壮生态以及各种各样的贡献者经验和背景的工具,使用起来通常会更有趣、更容易,总体上也更顺利。

React最初是一个小项目但现在广受欢迎并已经拥有了活跃的社区。没有社区是完美的,React社区也不例外,但就开源社区而言,它具有许多成功的要素。此外,React社区还包含其他较小的开源社区的子集。这令人生畏,因为React生态系统看起来非常庞大,但它也使社区更加健壮和多样。图1-2展示了一张React生态系统的地图。在本书的整个过程中,我提到了各种各样的库和项目,如果想要更多地了解React生态系统,我整理了一份指南放在我的博客上。我将持续更新它并确保它随生态系统演进。

图1-2 React生态系统的地图是丰富多彩的,甚至比我在这里表示的还要多

虽然开源(项目)可能是开发人员与React互动的主要方式,但你可能每天都在使用React开发的应用。许多公司以令人兴奋的不同方式使用React,下面是使用React来为其产品助力的一些公司:

这些公司不会盲目地追随JavaScript社区的趋势。他们有特殊的工程要求——影响到大量用户并且必须在严格的期限内交付产品。有人说,“我听说React不错;我们应该React化一切”,这种说法并不能打动经理们和其他的工程师们。公司和开发人员想要好工具来帮助他们更好地思考和快速行动,以便他们能够构建高强度、可伸缩和可靠的应用。

到目前为止,我已经从较高层次探讨了React:谁使用React,本书面向的人群,以及其他一些内容。我写本书的主要目的是教人使用React创建应用并使其成为一名工程师。React并不完美,但用其工作真的是一种乐趣,我已经看到很多团队用它做了很多伟大的事情。我喜欢写关于它的文章,用它进行创造,在会议上听到关于它的讨论,偶尔参与关于这个或那个模式的激烈辩论。

但如果不谈论React的缺点并说清它不能做什么,那我就是在帮倒忙。理解某物不能做什么和理解它能做什么同样重要。为什么?最好的工程决策和思考通常基于权衡取舍而不是基于个人观点或绝对真理(React从根本上就比工具X更好,因为我喜欢它)。就前者而言,可能不是在比较两种完全不同的技术(COBOL和JavaScript),甚至很大可能没有考虑那些根本不适合当前任务的技术;而对于后者,创建伟大的项目和解决工程挑战永远不应该跟个人观点有关。并不是人们的观点不重要(这当然不是事实),而是个人观点并不能让事情变得更好,甚至可能完全没有任何作用。

如果权衡是良好软件评估和讨论的基本,那么React中有什么权衡?首先,React有时被称为“只是视图”。这可能会被误解,因为它会让人认为React只是一个像Handlebars或Pug(曾用名Jade)的模板系统,或者它必须是MVC(模型-视图-控制器)架构的一部分。这都不对。React可以是这两种东西,但它可以做得更多。为了让事情更简单,我将更多地用React是什么而非React不是什么来描述React,例如,“只是视图”。React是一个声明性的基于组件的库,用于构建在各种平台上,甚至是未来的虚拟现实平台上(React VR)工作的用户界面:Web、原生、移动、服务器和桌面。

这导致了第一个权衡:React主要关注UI的视图方面。这意味着它并不是通过构建来完成更为全面的框架或库所要做的诸多工作。与Angular这样的框架进行一个快速比较可能有助于真正理解这一点。在最近的主要发布中,较之以前,Angular在概念和设计方面与React有了更多的共同点,但在其他方面,它涵盖了比React更大的领域。Angular包含了下列内置解决方案:

够多了,以我的经验看,人们对伴随一个框架而来的所有特性通常会有两种反应[2]。要么类似“哇,我不需要自己搞定所有这些事了”,或者是“哇,我都没法选择自己做事情的方式了”。Angular、Ember这类框架的好处是,它们通常有精心设计的方式来做事。例如,Angular中的路由是由内置的Angular路由器完成的,HTTP任务都是通过内置的HTTP例程完成的,等等。

这种方式没有什么本质上的错误。我曾在使用这种技术的团队中工作过,我也在采用更灵活的方式的团队中工作过,团队会选择“只把一件事做好”的技术。我们用这两种技术都取得了很好的效果。我个人倾向于“自主选择,专精一事”的方法,但这真的不是非此即彼,这只是权衡。对于HTTP、路由、数据建模(尽管它确实对视图中的数据流有自己的看法,我们稍后会看到),或者其他可能在Angular这类框架中看到的东西,React并没有内置的解决方案。如果团队认为没有单一框架就绝对做不了事,那么React可能不是最佳选择。但依我的经验看来,大多数团队都想要React的灵活性以及它带来的思维模型和直观API。

React的灵活方式的一个好处是可以自由地选择对于工作来说最好的工具。不喜欢某个HTTP库的工作方式?没问题,用其他库替换它。想要用不同的方式编写表单?放手去做,没问题!React提供了一组强大的原语。公平地说,其他框架,如Angular,通常也允许把东西换掉,但实际起作用的和社区支撑的做事方式通常是把所有东西内置或包含进来。

拥有更多自由的明显缺点是,如果习惯了像Angular或Ember这样的更全面的框架,那么需要为应用的不同领域想出或者找到自己的解决方案。这是好是坏取决于诸多因素,如团队开发人员的经验、工程管理偏好,以及其他特定于具体情况的因素。“通用型”和“专一型”这两种方式都有非常充分的理由。我更倾向于相信这种方法:将决定或创建正确工具的责任交给团队,随着时间推移去适应和做出灵活的、视情况而定的有关工具的决策。再考虑到无比广阔的JavaScript生态系统——终归会为正在解决的问题找到些东西。但最终,实际上优秀的、高影响力的团队会用这两种方式(有时在同一时间!)来构建他们的产品。

在继续之前,如果不提一下锁定,那就是我的失职了。JavaScript框架很少能真正地相互协作是一个无法回避的事实;通常不能让应用一部分是Angular,一部分是Ember,一部分是Backbone,一部分是React,至少在不细分每个部分或严格控制它们之间的交互的情况下不要这么做。当可以避免这种情况时,把自己置身于这样的处境中通常是没有意义的。通常,人们会在一个特定的应用中使用一个或暂时性地最多使用两个主要框架。

但是当需要改变时会发生什么?如果使用的工具像Angular那样具有广泛的职责,那么迁移应用时可能由于与框架的深度集成而需要完全重写。可以重写应用程序的较小部分,但不能只是替换几个函数就期望一切都正常工作。这正是React的闪耀之处。它使用了非常少的“魔法”方言。这并不意味着它能让迁移变得毫无难度,但它确实有助于摆脱与Angular这样的框架紧密集成所带来的迁移成本——迁移到框架上或从框架上迁移出来。

选择React时需要做出的另一个权衡是,它主要由Facebook开发和构建并且是为了满足Facebook的UI需求。如果你的应用与Facebook应用的UI需求有本质区别,那么使用React可能要吃不少苦头。幸运的是,大多数现代Web应用都在React的技术范围内,但也有一些应用不在此范围内。这可能还包括那些不适用现代Web应用的常规UI范式的应用,或是那些具有非常特殊性能需求的应用(如高速股票行情自动收录器)。然而,即使是这些应用,也可以用React来解决,尽管有些情况下需要更为专门的技术。

我们要讨论的最后一个权衡是React的实现和设计。融入React核心的系统会在组件中的数据发生变化时处理UI的更新。开发人员可以使用被称为生命周期方法的特定方法来挂载进它们执行更改的过程。我会在后面几章中详细介绍这些内容。React处理UI更新的系统使人们更为容易地专注于构建应用能够使用的模块化的、健壮的组件。React将UI与数据保持同步的大部分工作抽象分离出去是其受开发人员青睐的一个重要原因,也是其成为开发人员手中的一个强力工具的重要原因。但还不能说明驱动这个技术的“引擎”没有缺点或没有折中。

React是一种抽象,因此它作为抽象的代价仍然存在。由于React是以特定的方式构建并通过API向外暴露的,开发人员不会对其使用的系统有太多的可见性。这也意味着需要以一种地地道道的React方式来构建UI。幸运的是,React的API提供了“紧急出口”,让开发者可以深入到较低的抽象层级中。人们仍然可以使用jQuery这样的工具,但是需要以一种与React兼容的方式使用。这又是一种折中:一种更简单的思维模型,代价是不能完全以喜欢的方式做所有事情。

开发者不仅会失去对底层系统的一些可见性,还需要为React的行事方式买单。这往往会影响应用栈的一小部分(只有视图而不是数据、特殊的表单构建系统、数据建模等),但仍然会有影响。我希望是人们看到React的好处远远超过其学习成本,并且在使用它时所做的权衡通常会让使用者成为一个更好的开发者。但是,如果我假装React会神奇地解决所有的工程挑战,那就虚伪了。

我们已经讨论了一些React的高级特性。我认为React可以帮助研发团队更好地创建用户界面,并且这得益于React提供的思维模型和API。所有这一切背后隐藏着什么?React的主旨是推动简化复杂的任务并把不必要的复杂性从开发人员身上抽离出来。React试图将性能做得恰到好处,从而让研发人员腾出时间思考应用的其他方面。它这么做的主要方式之一就是鼓励开发人员使用声明式编程而不是命令式编程。开发人员要声明组件在不同状态下的行为和外观,而React的内部机制处理管理更新、更新UI以反映更改等的复杂性。

驱动这些的主要技术之一就是虚拟DOM。这种虚拟DOM是模仿或镜像存在于浏览器中的文档对象模型的数据结构或数据结构的集合。我之所以说“这种虚拟DOM”,是因为其他像Ember这样的框架采用了它们自己的类似技术的实现。通常,虚拟DOM会作为应用程序代码和浏览器DOM之间的中间层。虚拟DOM向开发人员隐藏了变更检测与管理的复杂性并将其转移到专门的抽象层。在接下来的小节中,我们将从更高层次来了解它是如何在React中起作用的。图1-3展示了DOM和虚拟DOM之间的关系,我们稍后将对此进行讨论。

图1-3 DOM和虚拟DOM。React的虚拟DOM处理数据的变更检测并将浏览器事件转换为React
组件可以理解和响应的事件。React的虚拟DOM还为性能专门优化了对DOM的更新操作

确保我们理解React的虚拟DOM的最佳途径就是首先检查我们对DOM的理解。如果觉得自己对DOM已经了然于心,可以选择跳过这部分。但如果不是,让我们从一个重要的问题开始:什么是DOM?DOM或文档对象模型是一个允许JavaScript程序与不同类型的文档(HTML、XML和SVG)进行交互的编程接口。它有标准驱动的规范,这意味着公共工作组已经建立了它应该具有的标准特性集以及行为方式。虽然存在其他实现,但是DOM几乎已经是Chrome、Firefox和Edge等Web浏览器的代名词了。

DOM提供了访问、存储和操纵文档不同部分的结构化方式。从较高层面来讲,DOM是一种反映了XML文档层次结构的树形结构。这个树结构由子树组成,子树由节点组成。这些(节点)是组成Web页面和应用的div和其他元素。

人们之前可能使用过DOM API——但他们没有意识到自己正在使用它。每当使用JavaScript中的方法访问、修改或者存储一些HTML文档相关的信息时,几乎可以肯定,人们就是在使用DOM或DOM相关的API。这意味着,你在JavaScript中使用的方法不全是JavaScript语言本身的一部分(document.findElemenyByIdquerySelectorAllalert等)。它们是更大的Web API集合(浏览器中的DOM和其他API)的一部分,这些API让人们能够与文档交互。图1-4展示了可能在Web页面中看到的DOM树结构的简化版本。

图1-4 这是DOM树结构的简化版本,使用人们熟悉的元素。暴露给
JavaScript的DOM API允许对树中的这些元素执行操作

用来更新或查询Web页面的常见方法或属性有getElementByIdparent.appendChildquerySelectorAllinnerHTML等。这些接口都是由宿主环境(这里指的是浏览器)提供的并允许JavaScript与DOM交互。没有这些能力,我们就没有那么有趣的Web应用可用了,也可能没有关于React的书可写了。

与DOM交互通常很简单,但在大型Web应用中可能会变得复杂。幸运的是,当使用React构建应用时我们通常不需要直接与DOM交互——我们基本上把它都交给了React。有些场景下我们可能希望绕过虚拟DOM直接与DOM交互,我们将在后面的几章对此进行讨论。

浏览器中的Web API让我们可以使用JavaScript通过DOM与Web文档进行交互。但如果我们已经能做到这一点,为什么在这之间还需要别的东西?首先我想说明的是,React实现虚拟DOM并不意味着常规Web API不好或者不如React好。没有它们,React就不能工作。然而,在更大的Web应用中直接使用DOM的确有一些痛点,通常这些痛点出现在变更检测方面。当数据变化时,我们希望通过更新UI来反映它,但很难以一种有效且易于理解的方式做到这点,所以React致力于解决这个问题。

出现这个问题的部分原因是浏览器处理与DOM交互的方式。当访问、修改或创建DOM元素时,浏览器常常要在一个结构化的树上执行查询来找到指定的元素。这只是访问一个元素,而且通常仅是更新的第一部分。通常情况下,作为更改的一部分,它不得不重新进行布局、缩放和其他操作——所有这些操作往往计算量都很大。虚拟DOM也无法绕过这个问题,但它可以在这些限制下帮助优化对DOM的更新。

当创建和管理一个处理随时间变化的数据的大型应用时,可能需要对DOM进行许多更改,这些更改通常会发生冲突或以不太理想的方式完成。这可能会导致一个过于复杂的系统,这个系统不但对工程师来说难以使用而且可能会导致用户体验不佳——这是“双输”。因此,性能是React设计和实现的另一个关键考虑因素。实现虚拟DOM有助于解决这个问题,但应该注意的是,它设计得只是“够快”而已。React的虚拟DOM更为重要的是提供了健壮的API、简单的思维模型和诸如跨浏览器兼容性等其他特性,而不是对性能的极端关注。我之所以强调这一点是因为人们可能听说虚拟DOM是某种“性能银弹”。它确实是高性能的,但它并不是神奇的“性能银弹”,最后我想说的是,React的许多其他好处对于使用React更为重要。

虚拟DOM是如何工作的?React的虚拟DOM与另一个软件世界有一些共同点——3D游戏。3D游戏有时会使用一个渲染过程,其工作原理大致如下:从游戏服务器获取信息,将信息发送到游戏世界(用户看到的视觉表现),确定需要对虚拟世界进行哪些更改,最后让显卡决定所需的最小更改。这种方法的一个优点是,只需要一些资源来处理增量更新,这种更新方式通常比全部更新快得多。

这是对3D游戏渲染和更新方式的粗略描述,当审视React执行更新的方式时,这个基本思想为我们提供了一个很好的参考。DOM变更做得不好的话代价可能会很大,所以React试图在更新UI方面更有效率并采用了类似3D游戏的方法。

如图1-5所示,React在内存中创建并维护了一个虚拟DOM,并且一个像React-DOM这样的渲染器基于更改对浏览器DOM进行更新。React可以执行智能更新并且只更新已更改的部分,因为它可以使用启发式对比来计算内存DOM的哪些部分需要更新到DOM。理论上讲,这比“脏检查”或其他更暴力的方法更加简洁优雅,但主要的实践意义是,开发者可以少考虑很多复杂的状态追踪。

图1-5 React的对比和更新流程。当改变发生时,React确定实际DOM和内存DOM的差异,然后对浏览器DOM执行高效更新。这个过程通常被称为diff(什么改变了)和patch(只更新改变的东西)过程

正如我所指出的,虚拟DOM有很多比速度更重要的东西。它通过设计得到高性能,并且通常会产生简单快速的应用,这样的速度对于现代Web应用的需要已经足够快了。工程师们对性能和更好的思维模型如此欣赏,以至于许多流行的JavaScript库都在创建自己版本的虚拟DOM或者变体的虚拟DOM。即使是在这些情况下,人们也倾向于认为虚拟DOM主要关注的是性能。性能是React的关键特性,但与简单相比较,它却是次要的。虚拟DOM一定程度上能够让开发人员推迟思考复杂的状态逻辑并专注于应用中其他更重要的部分。总而言之,速度和简单意味着更快乐的用户和更快乐的开发者——双赢!

我花了些时间来讨论虚拟DOM,但我并不想让人觉得它是使用React的重要部分。实际上,人们不需要过多考虑虚拟DOM是如何完成数据更新或如何对应用进行更改的。这正是React简单的地方:人们被解放出来去关注应用中最需要关注的那些部分。

React不只是用新颖的方式来处理数据随时间变化的问题,它还专注于将组件作为组织应用程序的范式。组件是React中最基本的单元。用React创建组件有几种不同的方法,后面的几章会介绍这些方法。以组件的方式思考不仅对于理解React的工作方式至关重要,而且对于理解如何在项目中更好地使用它也至关重要。

什么是组件?这是一个更大的话题。人们可能已经很熟悉组件的概念了,并且可能经常看到它们,即使他们可能没有意识到这一点。在设计和构建用户界面时,使用组件作为思维和可视化工具能够得到更好、更直观的应用设计与使用。可以将任意东西作为组件,尽管并不是所有东西作为组件都有意义。举个例子,如果认定整个界面是一个组件,并且没有子组件或进一步细分,那么你可能并没有帮到自己。相反,将界面的不同部分分解成可以组合、复用和易于重组的部分是很有帮助的。

为了开始以组件的方式思考,我们将查看一个示例界面并将其分解为不同的组成部分。图1-6展示了一个将在后续部分使用的示例界面。用户界面通常包含一些能够在界面的其他部分复用的元素,即使它们没有被复用,它们至少是独特的。这些不同元素——界面的独特元素——可以被认为是组件。图1-6中左边的界面被分解为右边的组件。

图1-6 一个界面被拆解为组件的例子。每一个不同部分都可以被认为是一个组件。
具有相同性质的重复项可以被认为是一个组件在不同数据上得到复用


练习1-1 组件思维

访问一个喜欢或常去的网站(如GitHub)并将其界面拆解成组件。当这样做的时候,你可能会发现自己把事物拆解成了不同的部分。那什么时候停止拆解呢?一个独立的字母应该作为一个组件吗?组件什么时候才算小呢?什么时候要将一组元素作为一个组件?


React组件具有良好的封装性、复用性和组合性。这些特性有助于为用户提供一种更简单、更优雅的方式来思考和构建用户界面。应用可以由清晰、简洁的分组组成,而不是像意大利面条那样一团乱。使用React来构建应用就像使用乐高积木来构建项目一样,不同的是构建应用时有取之不尽的“积木”。人们可能会遇到bug,但幸运的是不会踩到“积木”上。

在练习1-1中你实践了使用组件进行思考并将界面拆解成了组件。可以用很多方法来做这件事,并且这些方法可能没有特别的组织方式或惯例。这没关系。但是,当使用React中的组件时,考虑组件设计上的组织和一致性就非常重要了。需要设计独立的并且关注特定问题或一组相关问题的组件。

这有助于产生那种在应用中可移植的、逻辑分组的、易于移动和复用的组件。即使使用了其他库,设计良好的React组件也应该是相当独立的。将UI分解成组件可以让人更轻松地处理应用的不同部分。组件间的边界意味着功能和组织可以被良好地定义,而独立的组件则意味着它们可以更容易地被复用和移动。

React中的组件需要一起工作。这意味着可以将组件组合起来形成新的复合组件。组件组合是React最强大的部分之一。可以创建一个组件并让应用的其余部分复用它,这在大型应用中通常特别有帮助。如果身处一个大中型团队中,可以将组件发布到私有注册中心(npm或其他),其他团队可以很容易地将这些组件拉下来并将它们用到一个新的或已有的项目中。这可能不是一个适用于所有规模团队的场景,但即使是更小规模的团队也可以从React组件带来的代码复用中获益。

React组件的最后一个方面是生命周期方法。当组件经过其生命周期的不同时期时(挂载、更新、卸载等),可以使用这些可预测的、定义良好的方法。我们将在后面几章花很多时间在这些方法上。

现在对React中的组件有了更多的了解。对于个人开发者,React能让他们的生活更轻松。但在团队中呢?总的来说,React对个人开发者具有如此吸引力的原因也是使它成为团队最佳选择的原因。无论炒作或狂热的开发者如何鼓吹,同任何技术一样,对每个案例或项目来说,React并不是适用于每种情况或每个项目的完美解决方案。正如已经看到的,有很多事情React都没有做,但只要是React做的事情,它都做得非常好。

是什么使React成为大型团队和大型应用的优秀工具?首先,使用它很简单。简单和简易不是一回事。简易的方案往往又脏又快,最糟糕的是,它们可能欠下技术债。真正简单的技术是灵活和健壮的。React既提供了能够掌控的强大抽象,也提供了在必要时可下降到底层细节中去的方法。简单的技术更容易理解和使用,因为简化和删除不必要东西的困难工作已经完成了。在很多方面,React都让简单变得容易做到,它提供了有效方法却没有引入有害的“黑魔法”或不透明的API。

所有这些对个人开发者来说都很棒,但这种效应在更大的团队和组织中会被放大。尽管React肯定有改进和持续增长的空间,但使其成为一种简单灵活的技术的艰苦工作使工程团队们得到了回报。具有良好的思维模型的更简单的技术往往能减轻工程师的思维负担,让他们行动更快,这会产生更大的影响。作为额外的收获,一套更简单的工具对新员工来说更容易学习。尝试让一个团队新成员加入一个过于复杂的技术栈不仅要花时间培训工程师,还可能意味着新的开发者在一段时间内无法做出有意义的贡献。由于React力图仔细重新思考已建立的最佳实践,因此范式转换会有初始成本,但那之后通常是大而长期的收益。

与同一领域中的其他工具相比,React是一个相当不同的工具,但在职责和功能方面,React却是一个非常轻量的库。像Angular这样的框架要求使用者为更全面的API买单,而React却只关注应用的视图。这意味着将它与使用者当前的技术集成起来要简单得多,并且在其他方面为使用者留下了选择的空间。一些功能固化的框架和库要求使用者在要么全盘接受要么彻底不用之间进行抉择,但React“仅是视图”的范畴以及与JavaScript的全面互操作性意味着情况并非总是如此。

与其一下子全扑上去,使用者可以将不同的项目或工具逐步转换为React而又不必对其结构、构建技术栈或其他相关领域进行重大改变。对几乎所有技术来说,这都是理想的方式,而这正是React开始在Facebook尝试时的方法——在一个小项目上使用。从那里,随着越来越多的团队看到并体验到React的好处,它逐渐成长并扎根。这一切对使用者的团队意味着什么?这表示使用者无须冒险用React完全重写产品就可以评估React。

React的简单、非固化的本质以及性能让它非常适合大大小小的项目。随着使用者不断探索React,你将看到它是如何适合团队和项目的。

React是一个用来创建用户界面的库,最初由Facebook创建并开源。它是一个考虑了简单、高性能和组件化的JavaScript库。它没有提供创建应用的全面工具集,而是允许使用者选择如何实现以及使用什么来实现数据模型、服务器调用和其他应用的关注点。这些关键因素以及其他因素使得React可以成为大大小小的应用和团队的绝佳工具。下面简单总结一下React对几个典型角色的好处。

总而言之,React对刚入职的工程师来说比较容易学习,它可以减少应用中不必要的复杂性,还可以通过促进代码复用来减少技术债。花点时间回顾一下到目前为止了解到的React。

既然已经对React的背景和设计有了更多了解,那么我们就可以对React进行深入讨论了。在下一章,我们将创建第一个组件并进一步了解React是如何工作的。我们将了解更多关于虚拟DOM、React中的组件以及如何创建自己的组件的知识。

[1] 这实际上是作者开的一个小玩笑。一个叫Vanilla JS的框架声称自己是占有率最高的库,各大顶级公司如Facebook、Google、Amazon等都在使用它。它的官方文档还说自己的使用量是jQuery、Prototype、YUI等框架的总和还多。框架不需要下载,因为浏览器已经内置了这个框架。在它的官方网站中它非常严肃地声明了上述事实。但实际上,Vanilla JS指的就是原生的JavaScript,这个框架及它的官网只是一个玩笑而已,作者在这里用这个玩笑指代原生JavaScript。——译者注

[2] 绝非有意一语双关,看,这是一本关于反应(React)的书,就是这样。


相关图书

TypeScript全栈开发
TypeScript全栈开发
Java EE企业级应用开发实战(Spring Boot+Vue+Element)
Java EE企业级应用开发实战(Spring Boot+Vue+Element)
Vue.js全平台前端实战
Vue.js全平台前端实战
Flutter内核源码剖析
Flutter内核源码剖析
智能前端技术与实践
智能前端技术与实践
从0到1:ES6快速上手
从0到1:ES6快速上手

相关文章

相关课程