6.3 KiB
快速入门
创建和嵌套组件
React应用由组件组成,每个组件都是UI的一部分,组件拥有自己的外观和逻辑。
组件是返回标签的js函数
function MyButton() {
return (
<button>I'm a button</button>
);
}
上述已经声明了MyButton组件,可以将该组件嵌套到另一个组件中
export default function MyApp() {
return (
<div>
<h1>Welcome to my app</h1>
<MyButton />
</div>
);
}
react组件必须以大写字母开头,而html组件则是必须以小写字母开头,可以通过组件开头字母的大小写来区分html组件和react组件
jsx编写标签
上述返回标签的语法被称为jsx,大多数react项目都支持jsx。
jsx比html更加严格:
- 所有的标签都要有闭合标签(例如
<br/>) - 组件不能返回多个标签,只能返回一个标签,如果存在多个,必须将其包含到一个公共的父级
<div>或<>中function AboutPage() { return ( <> <h1>About</h1> <p>Hello there.<br />How do you do?</p> </> ); }
添加样式
React中,可以在标签中添加className属性来添加样式,其和html中的class工作方式相同
<img className="avatar" />
/* In your CSS */
.avatar {
border-radius: 50%;
}
显示数据
在jsx中,标签位于js中,而可以在标签内通过{}来计算js表达式并将其填充到标签中
return (
<h1>
{user.name}
</h1>
);
jsx还可以将表达式的值传递给标签属性,通过{}传递表达式的值
return (
<img
className="avatar"
src={user.imageUrl}
/>
);
同时,可以通过js表达式来复制css
const user = {
name: 'Hedy Lamarr',
imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
imageSize: 90,
};
export default function Profile() {
return (
<>
<h1>{user.name}</h1>
<img
className="avatar"
src={user.imageUrl}
alt={'Photo of ' + user.name}
style={{
width: user.imageSize,
height: user.imageSize
}}
/>
</>
);
}
条件渲染
在React中,没有特殊语法编写条件,故而可以在js中通过if条件引入jsx:
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
也可以使用如下方式:
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
渲染列表
可以通过如下方式将js数组渲染为列表
const products = [
{ title: 'Cabbage', id: 1 },
{ title: 'Garlic', id: 2 },
{ title: 'Apple', id: 3 },
];
const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
上述示例中,<li>有一个key属性,对于列表中的每个属性,都应该传递给其一个字符串或数字的key,用于在兄弟节点之间唯一标识该元素。
响应事件
可以在组件中声明事件处理函数来响应事件
function MyButton() {
function handleClick() {
alert('You clicked me!');
}
return (
<button onClick={handleClick}>
Click me
</button>
);
}
更新界面
如果希望组件维护状态信息,可以通过导入useState来完成
import { useState } from 'react';
function MyButton() {
const [count, setCount] = useState(0);
其中,count记录当前的状态,而setCount则是用于改变状态的函数,可以为数组中变量取任何名称。
import { useState } from 'react';
export default function MyApp() {
return (
<div>
<h1>Counters that update separately</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
Clicked {count} times
</button>
);
}
使用hook
以use开头的函数被称为hook,useState是react提供的一个内置hook。
hook比普通函数更为严格,只能在组件顶层或其他hook的顶层调用hook。如果想要在条件或循环中使用hook,请新建一个组件并在组件内部使用。
组件之间共享数据
如果想要将状态在多个组件之间共享,需要将状态提升存储到最近的公共父组件中
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>Counters that update together</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
Clicked {count} times
</button>
);
}
此时,由MyApp传递给MyButton的值称之为prop
jsx展开传递props
如果父组件想要将接收到的props全部传递给子组件,无需在子组件上列出props中全部属性,可以使用...props来进行展开
function Profile(props) {
return (
<div className="card">
<Avatar {...props} />
</div>
);
}
将jsx作为子组件传递
当采用如下形式时:
<Card>
<Avatar />
</Card>
其中,父组件接收到的prop中,children将代表接受到的子组件内容
import Avatar from './Avatar.js';
function Card({ children }) {
return (
<div className="card">
{children}
</div>
);
}
export default function Profile() {
return (
<Card>
<Avatar
size={100}
person={{
name: 'Katsuko Saruhashi',
imageId: 'YfeOqp2'
}}
/>
</Card>
);
}
此时,想要嵌套在父组件内部的子组件可以通过props.children来访问。
条件渲染
如果在某些条件下,组件不想显示任何内容,可以返回null
function Item({ name, isPacked }) {
if (isPacked) {
return null;
}
return <li className="item">{name}</li>;
}