JavaScript 基础
只讲 React 代码里常见的 JavaScript
要点
- 在 React 里卡住的地方,大多不是 React,而是 JavaScript。这里分成数组函数、比较符号、写法三类整理
- map、filter、...(展开)不会修改原数组,而是生成“新的数组”。所以和 React 的 state 很搭
- 遇到不认识的写法,先读下表里一句话的“规则”,再到演示里试一试
速查表
数组的函数
| 写法 | 规则(一句话) | 示例 |
|---|
| .map((x) => …) | 逐个取出,生成一个变换后的新数组 | members.map((m) => <li>{m.name}</li>) |
| .filter((x) => 条件) | 生成只保留符合条件的元素的新数组 | members.filter((m) => m.plan === "付费") |
| .find((x) => 条件) | 返回第一个符合条件的元素 | members.find((m) => m.id === 2) |
| .sort((a, b) => 数字) | 两两比较来排序。结果为负数时 a 排在前面 | [...items].sort((a, b) => a.price - b.price) |
| .slice(开始, 结束) | 从开始截取到结束的前一个(从 0 开始数) | items.slice(0, 6) |
| .reduce((合计, x) => …, 0) | 逐个查看,汇总成一个值(例如合计) | items.reduce((sum, i) => sum + i.price, 0) |
| .includes(x) | 是否包含 x(true/false) | name.includes(query) |
| .length | 数组是元素个数,字符串是字符数 | {members.length} 人 |
| .some((x) => 条件) | 是否至少有一个符合条件(true/false) | items.some((i) => i.stock === 0) |
| .join(分隔符) | 把数组用分隔符连接成一个字符串 | tags.join("、") |
比较与连接
| 写法 | 规则(一句话) | 示例 |
|---|
| === | 左边和右边是否相同 | plan === "付费" |
| !== | 左边和右边是否不同 | m.id !== id |
| > >= < <= | 大于・大于等于・小于・小于等于 | quantity >= stock |
| ! | 取反(true ↔ false) | !isOpen |
| && | 并且。在 JSX 中表示“符合就显示” | {error && <p>{error}</p>} |
| || | 或者 | !isDirty || isSubmitting |
| 条件 ? A : B | 符合就是 A,不符合就是 B | {open ? "关闭" : "打开"} |
| a ?? b | a 为空(null・undefined)时使用 b | user.name ?? "游客" |
| a?.b | 即使 a 为空也不报错,而是得到 undefined | user?.name |
写法
| 写法 | 规则(一句话) | 示例 |
|---|
| (x) => … | 创建函数(接收 x,执行 …) | () => setCount(count + 1) |
| (x) => { … } | 里面可以写多行的函数 | onClick={() => { reset(); setSent(false) }} |
| const 和 let | const 不重新赋值,let 之后可以重新赋值 | let sorted = filtered |
| const [a, setA] = … | 给返回的两个值起名并取出 | const [count, setCount] = useState(0) |
| const { a, b } = … | 从对象({ })里按名字只取出要用的部分 | const { user } = useAuth() |
| function X({ a }) | 按名字接收传给组件的值(props) | function Card({ title }) { … } |
| `…${x}…` | 在字符串里插入值(模板字符串) | `${count} 条` |
| [...x, 新增] | 复制数组,并在末尾追加后得到的新数组 | setMembers([...members, newMember]) |
| { ...x, 键: 值 } | 复制一个对象,只改一处后得到的新对象 | { ...member, id: 7 } |
| import/export | 使用其他文件的组件/提供给其他文件使用 | import { Button } from "./button" |
| async/await | 等待耗时的操作(例如获取数据)完成 | const res = await fetch(url) |
动手试试
import { useState } from "react"
const initialMembers = [
{ id: 1, name: "张伟", plan: "付费" },
{ id: 2, name: "李娜", plan: "免费" },
{ id: 3, name: "王芳", plan: "付费" },
]
export default function App() {
const [members, setMembers] = useState(initialMembers)
const [paidOnly, setPaidOnly] = useState(false)
const shown = paidOnly ? members.filter((member) => member.plan === "付费") : members
function addMember() {
const newId = members.length + 1
setMembers([...members, { id: newId, name: "会员" + newId, plan: "免费" }])
}
return (
<div style={{ padding: 16, fontFamily: "sans-serif" }}>
<div style={{ display: "flex", gap: 8 }}>
{}
<button onClick={() => setPaidOnly(!paidOnly)}>{paidOnly ? "查看全部" : "只看付费"}</button>
<button onClick={() => addMember()}>加 1 人</button>
</div>
<p>共 {shown.length} 人</p>
{}
<ul>
{shown.map((member) => (
<li key={member.id}>
{member.name}({member.plan})
</li>
))}
</ul>
</div>
)
}- 点一下“只看付费”(filter 会生成只有付费会员的新数组)
- 把 "付费" 改成 "免费" 试试
- 多点几次“加 1 人”([...members, 新成员] 会在末尾逐个增加)