阅读说明
软件版本
- React v18.3.1
- React Dom v18.3.1
- Vite v5.3.1
- vitejs/plugin-react v4.3.1
- TypeScript v5.2.2
- @types/react v18.3.3
- @types/react-dom v18.3.0
介绍
React是一个开源的前端JavaScript库,用于构建用户界面。用户界面由按钮、文本和图像等小单元内容构建而成。React帮助你把它们组合成可重用、可嵌套的组件。从we端网站到移动端应用,屏幕上的所有内容都可以被分解成组件。
它由Facebook维护,并在2013年首次发布。React的核心特性是其组件化架构,允许开发者使用名为“React组件”的可重用代码片段构建复杂的用户界面。
体验React
直接将以下代码保存在本地,打开页面查看效果。
例子一
|
|
在线预览。
例子二
|
|
在线预览。
以上代码仅适合快速了解React的使用。为什么?你可以看到用到了<script type="text/babel">
,它是一种在早期React和其他使用ES6模块语法的项目中使用的脚本标记方式。
- Babel是一个广泛使用的JavaScript编译器,它可以将ES6+语法转换为向后兼容的JavaScript语法(通常是 ES5),也可以将JSX解析成JavaScript,这样代码就可以在更多的环境中运行,包括旧版浏览器。
text/babel
是一个自定义的MIME类型,它不是一个官方标准,而是一种约定俗成的用法,使用之前确保页面引入了Babel的polyfill和相关设置。
在页面加载时,Babel会自动检测type="text/babel"
的脚本,并将其内容转译成ES5代码,然后运行。
这种写法并不是一个长期推荐的解决方案,因为它依赖于全局的Babel配置,可能会与其他构建工具或模块打包器冲突。
现代前端开发通常使用构建工具(如Webpack、Rollup、Vite等)来处理代码转译和打包,这些工具提供了更高效、更灵活、更强大的配置选项和处理方式。
data-type="module"
是告诉Babel polyfill该脚本应该被视为模块来处理。
使用构建工具运行React
这里使用Vite。
|
|
按照提示处理就行,我这里选的是:
Select a framework: React
Select a variant: TypeScript
接着:
|
|
将得到以下目录:
|
|
组件
组件是React的核心概念之一,它们是构建用户界面(UI)的基础。一个组件是UI(用户界面)的一部分,它拥有自己的逻辑和外观。组件可以小到一个按钮,也可以大到整个页面。
每个React组件都是一个JavaScript函数,它会返回一些标签,React会将这些标签渲染到浏览器上。
是的,你没理解错,React组件会将HTML标签和逻辑耦合在一起。
为什么?官方说法是web交互性越来越强,逻辑越来越决定页面中的内容,JavaScript控制着HTML的内容。
乍眼一看还是很晦涩难懂的,以下是个人的理解看法:
例如JS里可以看到
createElement
、innerHTML
等等,都是做着渲染HTML的事情,这种写法和过程是很冗长很混乱的,React的出现,只是将这个过程用JSX更直观地放在了组件中进行,并且它做的更简单、易懂。再加上都是JavaScript的东西,不需要再学一些特有的东西,结合友好的文档,有JS基础的人,学起来会相对舒服一些。
就像这样:
|
|
这就是React组件的定义方式,MyApp
是组件名称,名称必须以大写字母开头,换句话说你可以由此作为依据来辨别React组件,因为HTML标签必须是小写字母开头的。
<h1>Hello, world!</h1>
,这段看起来像HTML,实际上是JavaScript,这种语法被称为JSX,它允许你在JavaScript中嵌入标签。JSX看起来和HTML很像,但它的语法更加严格并且可以动态展示信息。
但JSX并不属于React,它不是React的特性,了解更多关于JSX(强烈建议先了解完再回过头来看)。
简单的JSX写在一行没问题,但如果JSX很多,要换行应该怎么写?就像下面这样:
|
|
当JSX和return不在同一行的时候,必须用括号把它包裹起来,否则return之后的代码都会被忽略。
使用组件
导出和导入
要使用组件就要先将组件导出,会用到export,它是JavaScript的标准语法,这样你就能够在其他文件中使用import进行导入。
新建一个Buttons.tsx
文件。
导出的方式有两种:
- 默认导出:
export default
- 具名导出:
export
一个模块文件中可以有多个具名导出,但只允许有一个默认导出。
默认导出:
|
|
在另一个文件App.tsx
中导入:
|
|
具名导出:
|
|
另一个文件App.tsx
中导入:
|
|
通常,文件中仅包含一个组件时,人们会选择默认导出,而当文件中包含多个组件或某个值需要导出时,则会选择具名导出。
无论选择哪种方式,请记得给你的组件和相应的文件命名一个有意义的名字。不建议创建未命名的组件,比如 export default () => {}
,因为这样会使得调试变得异常困难。
子组件
通过上面的例子可以看到,Button
是一个子组件,同时也是一个函数,它返回了JSX,并嵌套进了Buttons
父组件中,然后再被嵌套进App
组件中。
这个过程可以实现俄罗斯套娃式嵌套JSX,再联合{}
大括号可以将组件玩出花来。
Props
React组件使用props
来互相通信。每个父组件都可以提供props
给它的子组件,从而将一些信息传递给它。Props
可能会让你想起 HTML 属性,但你可以通过它们传递任何JavaScript值,包括对象、数组和函数。
以<img>
HTML标签举例,它的属性(在HTML标准里称为attributes)有:
- alt
- src
- width
- height
- srcset
- loading
- crossorigin
而在上面的例子中:
|
|
name
就是组件的Props,类似于<img>
标签的属性Attributes。
获取Props
|
|
可以看到props
这个形参,这样就能够接收所有赋值给Button
组件的props。
当然,你也可以这么写:
|
|
function Button({ name })
,这种形参的写法叫做解构赋值,是JavaScript的表达式。
渲染列表
|
|
也可以这么写:
|
|
const items = names.map(name => <li>...</li>);
这种写法叫做箭头函数表达式。
- 箭头函数
=>
之后的表达式会被隐式地返回,因此可以省略return语句。- 箭头函数
=> {
后面的部分被称为块函数体(Block body),它支持多行代码的写法,但必须用显式的return语句返回。
其中<li key={name}>
的key
属性是必须的,它的值起到唯一标识作用,实际使用不应该是name,而应是id。
因为这些key会告诉React,每个组件对应着数组里的哪一项,所以React可以把它们匹配起来。这在数组项进行移动(例如排序)、插入或删除等操作时非常重要。一个合适的key
可以帮助React 推断发生了什么,从而得以正确地更新DOM树。
JSX
JSX和React是两个相互独立的东西,JSX是JavaScript语法扩展,是一种语法扩展,而React是一个JavaScript库。
JSX看起来就是HTML标签,到底和HTML有什么不同?
规则约束
标签必须闭合
<img>
这种自闭和的标签,必须书写成<img />
。<li>
这种有开始标签,就必须得有结束标签。<li></li>
。
使用驼峰命名法给属性命名
JSX最终会被转化为JavaScript,而JSX中的属性也会变成JavaScript对象中的键值对。在你自己的组件中,经常会遇到需要用变量的方式读取这些属性的时候。
但JavaScript对变量的命名有限制。例如,变量名称不能包含-
符号或者像class
这样的保留字。
这就是为什么在React中,大部分HTML和SVG属性都用驼峰式命名法表示。
例如,需要用strokeWidth
代替stroke-width
。由于class
是一个保留字,所以在React中需要用className
来代替。这也是 DOM 属性中的命名。
JSX写法:
|
|
HTML写法:
|
|
如果在编写JSX时有错误,React也会在编译时告诉你。
如果你需要用到aria-和data-这样的属性时,使用驼峰命名法并不适用,这是HTML历史原因。
JSX:
|
|
编译以后的HTML:
|
|
应该这么写,JSX:
|
|
编译以后的HTML:
|
|
只能返回一个根元素
如果想要在一个组件中包含多个元素,需要用一个父标签把它们包裹起来。
例如,你可以使用一个 <div>
标签:
|
|
如果你不想在标签中增加一个额外的 <div>
,可以用 <>
和 </>
元素来代替:
|
|
这个空标签被称作Fragment。React Fragment允许你将子元素分组,而不会在 HTML 结构中添加额外节点。
为什么多个 JSX 标签需要被一个父元素包裹?
JSX 虽然看起来很像 HTML,但在底层其实被转化为了 JavaScript 对象,你不能在一个函数中返回多个对象,除非用一个数组把他们包装起来。这就是为什么多个 JSX 标签必须要用一个父元素或者 Fragment 来包裹。
以上,不符合规则的写法都不是JSX,如果你有大量的HTML需要转换成JSX,可以用在线转换器。
在JSX中使用JavaScript
动态指定属性的值,需要用到变量,在JSX中可以用{变量名}
以此来访问JavaScript变量。
|
|
在{}
(大括号)中,可以使用任何JavaScript表达式,例如函数调用、三元表达式、与运算符 &&。
这里举例函数调用:
|
|
双大括号{{}}
,你可能会在别的React应用中看到这种写法,它其实是大括号里的一个对象。
一般会用在写内联样式的时候(实际情况当然是用class类名解决样式问题才更好):
|
|
换一个写法,更容易识别:
|
|
样式名称
background-color
遵循驼峰命名规则所以是backgroundColor
。
当然,你也可以这么写,这样更简洁:
|
|
使用限制
在JSX中,只有两种情况可以使用{}
大括号:
- 用作JSX标签内的文本:
<h1>{name}</h1>
是有效的,但是<{tag}>text</{tag}>
无效。 - 用作紧跟在
=
符号后的属性:src={avatar}
会读取avatar
变量,但是src="{avatar}"
只会传一个字符串{avatar}
。
结尾
官方文档写的其实已经很好很全面很通俗易懂了,为什么我还会写这下一篇文章?
官方文档乍眼一看还是比较困难的,没有一个概览,对我来说还是散乱了一些,看下来以后发现文档确实写的很好,我做的只是将这些知识重新整理了下顺序,做的相对集中一点,这个过程本身也是一种学习、吸收的方式。
所以你可以看到,文中讲的内容并不全面,并不打算重复文档中已经的东西,虽然是个知识的搬运工,做到切合文章的主题足以。