参考文章
React 18 快速入门
创建和嵌套组件
React 应用程序是由 组件 组成的。一个组件是 UI(用户界面)的一部分,它拥有自己的逻辑和外观。组件可以小到一个按钮,也可以大到整个页面。
React 组件是返回标签的 JavaScript 函数:
function MyButton() {return (<button>I'm a button</button>);
}
至此,已经声明了 MyButton
,可以把它嵌套到另一个组件中:
export default function MyApp() {return (<div><h1>Welcome to my app</h1><MyButton /></div>);
}
注意:<MyButton />
是以大写字母开头的。可以根据此来区分 React 组件。React 组件必须以大写字母开头,而 HTML 标签则必须是小写字母。
使用 JSX 编写标签
上面所使用的标签语法被称为 JSX。它是可选的,但大多数 React 项目会使用 JSX,主要是它很方便。所有 我们推荐的本地开发工具 都支持 JSX,开箱即用。
JSX 比 HTML 更加严格。必须闭合标签,如 <br/>
。组件也不能返回多个 JSX 标签。必须将它们包裹到一个共享的父级中,比如 <div>...<div/>
或使用空的 <>...</>
包裹:
function AboutPage() {return (<><h1>About</h1><p>Hello there.<br />How do you do?</p></>);
}
如果有大量的 HTML 需要移植到 JSX 中,可以使用 在线转换器。
添加样式
在 React 中,可以使用 className
来指定一个 CSS 的 class。它与 HTML 的 class
属性的工作方式相同:
<img className="avatar" />
然后,可以在一个单独的 CSS 文件中为它编写 CSS 规则:
/* In your CSS */
.avatar {border-radius: 50%;
}
React 并没有规定如何添加 CSS 文件。最简单的方式,可以在 HTML 中添加一个<link>
标签。如果使用了构建工具或框架,请阅读其文档,以了解如何将 CSS 文件添加到项目中。
显示数据
JSX 会让你把标签放到 JavaScript 中。而大括号会让你 “回到” JavaScript 中,这样就可以从代码中嵌入一些变量并展示给用户。例如,这将显示 user.name
:
return (<h1>{user.name}</h1>
);
还可以将 JSX 属性 “转义到 JavaScript”,但必须使用大括号 而非 引号。例如,className="avatar"
是将 "avatar"
字符串传递给 className
,作为 CSS 的 class。但 src={user.imageUrl}
会读取 JavaScript 的 user.imageUrl
变量,然后将该值作为 src
属性传递:
return (<imgclassName="avatar"src={user.imageUrl}/>
);
也可以把更为复杂的表达式放入 JSX 的大括号内,例如 字符串拼接:
const user = {name: 'Hedy Lamarr',imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',imageSize: 90,
};export default function Profile() {return (<><h1>{user.name}</h1><imgclassName="avatar"src={user.imageUrl}alt={'Photo of ' + user.name}style={{width: user.imageSize,height: user.imageSize}}/></>);
}
在上面示例中,style={{}}
并不是一个特殊的语法,而是 style={ }
JSX 大括号内的一个普通 {}
对象。当样式依赖于 JavaScript 变量时,可以使用 style
属性。
条件渲染
在 React 中,没有特殊的语法来编写条件。因此,将使用与编写常规 JavaScript 代码时相同的技术。例如,可以使用 if
语句根据条件引入 JSX:
let content;if (isLoggedIn) {content = <AdminPanel />;
} else {content = <LoginForm />;
}return (<div>{content}</div>
);
如果喜欢更为紧凑的代码,可以使用 条件 ?
运算符。与 if
不同的是,它工作于 JSX 内部:
<div>{ isLoggedIn ? (<AdminPanel />) : (<LoginForm />) }
</div>
当不需要 else
分支时,还可以使用 逻辑 &&
语法:
<div>{ isLoggedIn && <AdminPanel /> }
</div>
所有这些方法也适用于有条件地指定属性。如果对 JavaScript 语法不熟悉,可以从一直使用 if...else
开始。
渲染列表
将依赖 JavaScript 的特性,例如 for
循环 和 array 的 map()
函数 来渲染组件列表。
例如,假设有一个产品数组:
const products = [{ title: 'Cabbage', isFruit: false, id: 1 },{ title: 'Garlic', isFruit: false, id: 2 },{ title: 'Apple', isFruit: true, id: 3 },
];
在组件中,使用 map()
函数将一个产品数组,转换为 <li>
标签的元素列表:
export default function ShoppingList() {const listItems = products.map(product =><likey={product.id}style={{color: product.isFruit ? 'magenta' : 'darkgreen'}}>{product.title}</li>);return (<ul>{listItems}</ul>);
}
注意: <li>
有一个 key
属性。对于列表中的每一个元素,应该传递一个字符串或者数字给 key
,用于在其兄弟节点中唯一标识该元素。通常,key 应该来自你的数据,比如,数据库中的 ID。如果在后续插入、删除或重新排序这些项目,React 将依靠提供的 key 来思考发生了什么。
响应事件
可以通过在组件中声明 事件处理 函数来响应事件:
function MyButton() {function handleClick() {alert('You clicked me!');}return (<button onClick={handleClick}>Click me</button>);
}
注意:onClick={handleClick}
的结尾没有小括号!不要 调用 事件处理函数:只需 传递给事件 即可。当用户点击按钮时,React 会调用事件处理函数。
更新界面
通常,会希望组件 “记住” 一些信息并展示出来。例如,想计算一个按钮被点击的次数。要做到这一点,需要在组件中添加 state。
首先,从 React 引入 useState
:
import { useState } from 'react';
现在可以在组件中声明一个 state 变量:
function MyButton() {const [count, setCount] = useState(0);}
将从 useState
中获得两样东西:当前的 state(count
),以及用于更新它的函数(setCount
)。可以给它们起任何名字,但按照惯例,需要像这样 [something, setSomething]
为它们命名。
第一次显示按钮时,count
的值为 0
,因为把 0
传给了 useState()
。当想改变 state 时,调用 setCount()
并将新的值传递给它。点击该按钮,计数器将递增:
function MyButton() {const [count, setCount] = useState(0);function handleClick() {setCount(count + 1);}return (<button onClick={handleClick}>Clicked {count} times</button>);
}
React 将再次调用组件函数。这次,count
会变成 1
。接着,变成 2
。以此类推。
如果多次渲染同一个组件,每个组件都会拥有自己的 state。你可以尝试点击不同的按钮:
export default function MyApp() {return (<div><h1>Counters that update separately</h1><MyButton /><MyButton /></div>);
}
注意:每个按钮会 “记住” 自己的 count
,而不影响其他按钮。
使用 Hook
以 use
开头的函数被称为 Hook。useState
是 React 提供的一个内置 Hook。可以在 React API 参考 中找到其他内置的 Hook。也可以通过组合现有的 Hook 来编写属于自己的 Hook。