Next学习手册(五) - Props

Next学习手册(五) - Props

九月 29, 2023

到目前为止,如果要重用<Header/>组件,它将两次显示相同的内容。

1
2
3
4
5
6
7
8
9
10
11
12
function Header() {
return <h1>Develop. Preview. Ship. 🚀</h1>;
}

function HomePage() {
return (
<div>
<Header />
<Header />
</div>
);
}

但是,如果你想传递不同的文本,或者因为从外部源获取数据而不提前知道信息,该怎么办?

常规HTML元素具有一些属性,您可以使用这些属性来传递更改这些元素行为的信息。例如,更改<img>元素的src属性会更改所显示的图像。更改<a>标记的href属性会更改链接的目的地。

以同样的方式,您可以将信息片段作为属性传递给React组件。这些被称为Props。

与JavaScript函数类似,您可以设计接受自定义参数(或道具)的组件,这些参数可以更改组件的行为或在屏幕上显示的内容。然后,您可以将这些道具从父组件传递到子组件。

  • 注意:在React中,数据沿着组件树向下流动。这被称为单向数据流。状态(将在下一节中讨论)可以作为道具从父组件传递到子组件。

Using props

在HomePage组件中,可以将自定义标题道具传递给Header组件,就像传递HTML属性一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
// function Header() {
// return <h1>Develop. Preview. Ship. 🚀</h1>
// }

function HomePage() {
return (
<div>
<Header title="React 💙" />
</div>
);
}

// ReactDOM.render(<HomePage />, app)

子组件Header可以接受这些道具作为其第一个函数参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
function Header(props) {
// return <h1>Develop. Preview. Ship. 🚀</h1>
// }

// function HomePage() {
// return (
// <div>
// <Header title="React 💙" />
// </div>
// )
// }

// ReactDOM.render(<HomePage />, app)

如果使用console.log()props,您可以看到它是一个具有title属性的对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Header(props) {
console.log(props) // { title: "React 💙" }
// return <h1>React 💙</h1>
// }

// function HomePage() {
// return (
// <div>
// <Header title="React 💙" />
// </div>
// )
// }

// ReactDOM.render(<HomePage />, app)

由于props是一个对象,您可以使用对象析构函数来显式命名函数参数中的props值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function Header({ title }) {
console.log(title) // "React 💙"
// return <h1>React 💙</h1>
// }

// function HomePage() {
// return (
// <div>
// <Header title="React 💙" />
// </div>
// )
// }

// ReactDOM.render(<HomePage />, app)

然后,您可以用标题变量替换<h1>标记的内容。

1
2
3
4
function Header({ title }) {
console.log(title);
return <h1>title</h1>;
}

如果你在浏览器中打开你的项目,你会看到它显示的是实际的单词“title”。这是因为React认为您打算向DOM呈现一个纯文本字符串。

您需要一种方法来向React表示这是一个JavaScript变量。

Using Variables in JSX

要使用您定义的变量,您可以使用大括号{},这是一种特殊的JSX语法,允许您直接在JSX标记中编写常规JavaScript。

1
2
3
4
// function Header({title}) {
// console.log(title)
return <h1>{title}</h1>;
// }

当在“JSX land”中时,您可以将大括号视为输入“JavaScript land”的一种方式。您可以在大括号内添加任何JavaScript表达式(计算结果为单个值的表达式)。例如:

  1. 带有点符号的对象属性
1
2
3
function Header(props) {
return <h1>{props.title}</h1>;
}
  1. 模板文字
1
2
3
function Header({ title }) {
return <h1>{`Cool ${title}`}</h1>;
}
  1. 函数的返回值
1
2
3
4
5
6
7
8
9
10
11
function createTitle(title) {
if (title) {
return title;
} else {
return 'Default title';
}
}

function Header({ title }) {
return <h1>{createTitle(title)}</h1>;
}
  1. 三元运算符
1
2
3
function Header({ title }) {
return <h1>{title ? title : 'Default Title'}</h1>;
}

现在,可以将任何字符串传递给标题道具,由于您已经用三元运算符说明了组件中的默认情况,因此您甚至根本无法传递标题道具:

1
2
3
4
5
6
7
8
9
10
11
function Header({ title }) {
return <h1>{title ? title : 'Default title'}</h1>;
}

function HomePage() {
return (
<div>
<Header />
</div>
);
}

组件现在接受一个通用的标题道具,您可以在应用程序的不同部分中重用它。您只需更改标题:

1
2
3
4
5
6
7
8
function HomePage() {
return (
<div>
<Header title="React 💙" />
<Header title="A new title" />
</div>
);
}

Iterating through lists

通常需要将数据显示为列表。您可以使用数组方法来操作数据,并生成样式相同但包含不同信息的UI元素。

  • 注意:React在数据获取方面是无限制的,这意味着您可以选择最适合您需求的解决方案。稍后,我们将在Next.js中讨论数据获取选项。但目前,您可以使用一个简单的数组来表示数据。

将名称数组添加到主页组件:

1
2
3
4
5
6
7
8
9
function HomePage() {
const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];

return (
<div>
<Header title="Develop. Preview. Ship. 🚀" />
</div>
);
}

然后,您可以使用array.map()方法迭代数组,并使用箭头函数将名称映射到列表项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function HomePage() {
const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];

return (
<div>
<Header title="Develop. Preview. Ship. 🚀" />
<ul>
{names.map((name) => (
<li>{name}</li>
))}
</ul>
</div>
);
}

请注意,如何使用大括号在“JavaScript”和“JSX”区域中来回编织的。

如果您运行此代码,React将向我们发出关于缺少密钥道具的警告。这是因为React需要一些东西来唯一标识数组中的项,这样它就知道要更新DOM中的哪些元素。

现在可以使用这些名称,因为它们当前是唯一的,但建议使用保证唯一的名称,如物品ID。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function HomePage() {
const names = ['Ada Lovelace', 'Grace Hopper', 'Margaret Hamilton'];

return (
<div>
<Header title="Develop. Preview. Ship. 🚀" />
<ul>
{names.map((name) => (
<li key={name}>{name}</li>
))}
</ul>
</div>
);
}