React快速入门学习笔记
React快速入门笔记
创建和嵌套组件
React 应用程序是由 组件 组成的。一个组件是 UI(用户界面)的一部分,它拥有自己的逻辑和外观。
React 组件是返回标签的 JavaScript 函数:
1 | function MyButton() { |
完成以上代码,你就创建了一个MyButton组件,现在将它嵌套到另外一个组件中
1 | export default function MyApp() { |
React 组件必须以大写字母开头,而 HTML 标签则必须是小写字母。例如以上代码的**
For example:
1 | function MyButton() { |
export default
是 JavaScript 模块系统中的一个关键字,用于从一个模块导出一个默认的值或函数或类。
使用 JSX 编写标签
JSX 是 JavaScript XML 的缩写,是一种 JavaScript 的语法扩展,它允许开发者在 JavaScript 文件中编写类似 HTML 的代码。
JSX 比 HTML 更加严格。你必须闭合标签,如 <br />
。你的组件也不能返回多个 JSX 标签。你必须将它们包裹到一个共享的父级中。
添加样式
在 React 中,你可以使用 className
来指定一个 CSS 的 class。它与 HTML 的 class
属性的工作方式相同:
1 | <img className="avatar" /> |
然后,你可以在一个单独的 CSS 文件中为它编写 CSS 规则:
1 | /* In your CSS */ |
React 并没有规定你如何添加 CSS 文件。最简单的方式是使用 HTML 的 `` 标签。
显示数据
JSX 会让你把标签放到 JavaScript 中。而大括号会让你 “回到” JavaScript 中,这样你就可以从你的代码中嵌入一些变量并展示给用户
1 | return ( |
你还可以将 JSX 属性 “转义到 JavaScript”,但你必须使用大括号 而非 引号。例如,className="avatar"
是将 "avatar"
字符串传递给 className
,作为 CSS 的 class。但 src={user.imageUrl}
会读取 JavaScript 的 user.imageUrl
变量,然后将该值作为 src
属性传递:
1 | return ( |
也可以把更为复杂的表达式放入 JSX 的大括号内
1 | const user = { |
条件渲染
React 没有特殊的语法来编写条件语句,因此你使用的就是普通的 JavaScript 代码。例如使用 if
语句根据条件引入 JSX:
1 | let content; |
如果你喜欢更为紧凑的代码,可以使用 条件 ?
运算符。与 if
不同的是,它工作于 JSX 内部:
1 | <div> |
当你不需要 else
分支时,你也可以使用更简短的 &&
1 | <div> |
渲染列表
你将依赖 JavaScript 的特性,例如 for
循环 和 array 的 map()
函数 来渲染组件列表。
1 | const products = [ |
在你的组件中,使用 map()
函数将这个数组转换为 <li>
标签构成的列表:
1 | const listItems = products.map(product => |
注意, <li>
有一个 key
属性。对于列表中的每一个元素,你都应该传递一个字符串或者数字给 key
,用于在其兄弟节点中唯一标识该元素。通常 key 来自你的数据,比如数据库中的 ID。如果你在后续插入、删除或重新排序这些项目,React 将依靠你提供的 key 来思考发生了什么。
1 | const products = [ |
响应事件
你可以通过在组件中声明 事件处理 函数来响应事件:
1 | function MyButton() { |
注意,onClick={handleClick}
的结尾没有小括号!不要 调用 事件处理函数:你只需 把函数传递给事件 即可。当用户点击按钮时 React 会调用你传递的事件处理函数。
更新界面
通常你会希望你的组件 “记住” 一些信息并展示出来,比如一个按钮被点击的次数。要做到这一点,你需要在你的组件中添加 state。
首先,从 React 引入 useState
:
1 | import { useState } from 'react'; |
现在你可以在你的组件中声明一个 state 变量:
1 | function MyButton() { |
你将从 useState
中获得两样东西:当前的 state(count
),以及用于更新它的函数(setCount
)。你可以给它们起任何名字,但按照惯例会像 [something, setSomething]
这样为它们命名。
第一次显示按钮时,count
的值为 0
,因为你把 0
传给了 useState()
。当你想改变 state 时,调用 setCount()
并将新的值传递给它。点击该按钮计数器将递增:
1 | function MyButton() { |
React 将再次调用你的组件函数。第一次 count
变成 1
。接着点击会变成 2
。继续点击会逐步递增。
如果你多次渲染同一个组件,每个组件都会拥有自己的 state。你可以尝试点击不同的按钮:
1 | import { useState } from 'react'; |
每个按钮会 “记住” 自己的 count
,而不影响其他按钮
组件间共享数据
在前面的示例中,每个 MyButton
都有自己独立的 count
,当每个按钮被点击时,只有被点击按钮的 count
才会发生改变:
然而,你经常需要组件 共享数据并一起更新。
为了使得 MyButton
组件显示相同的 count
并一起更新,你需要将各个按钮的 state “向上” 移动到最接近包含所有按钮的组件之中。
在这个示例中,它是 MyApp
:
此刻,当你点击任何一个按钮时,MyApp
中的 count
都将改变,同时会改变 MyButton
中的两个 count。具体代码如下:
首先,将 MyButton
的 state 上移到 MyApp
中:
1 | export default function MyApp() { |
接着,将 MyApp
中的点击事件处理函数以及 state 一同向下传递到 每个 MyButton
中。你可以使用 JSX 的大括号向 MyButton
传递信息。就像之前向 <img>
等内置标签所做的那样:
1 | export default function MyApp() { |
使用这种方式传递的信息被称作 prop。此时 MyApp
组件包含了 count
state 以及 handleClick
事件处理函数,并将它们作为 prop 传递给 了每个按钮。
最后,改变 MyButton
以 读取 从父组件传递来的 prop:
1 | function MyButton({ count, onClick }) { |
当你点击按钮时,onClick
处理程序会启动。每个按钮的 onClick
prop 会被设置为 MyApp
内的 handleClick
函数,所以函数内的代码会被执行。该代码会调用 setCount(count + 1)
,使得 state 变量 count
递增。新的 count
值会被作为 prop 传递给每个按钮,因此它们每次展示的都是最新的值。这被称为“状态提升”。通过向上移动 state,我们实现了在组件间共享它。
1 | import { useState } from 'react'; |