Featured image of post 学习React第1章-组件与道具

学习React第1章-组件与道具

这篇笔记介绍了React的JSX语法、组件和道具的基本概念,并通过一个个人资料卡片的实例展示了如何使用这些概念构建React应用。

JSX

React采用“声明式”布局来书写代码,这可以让代码更好反映出真实的用户界面,加快我们的开发速度。

image

我们在React中使用JSX语言。这是一种融合了HTMLCSSJavaScript的语言,最终被Babel翻译成标准的JavaScript

It is called JSX, and it is a syntax extension to JavaScript. We recommend using it with React to describe what the UI should look like. JSX may remind you of a template language, but it comes with the full power of JavaScript. ——React Doc

1
2
3
4
5
6
function getGreeting(user) {
  if (user) {
    return <h1>Hello, {formatName(user)}!</h1>;
  }
  return <h1>Hello, Stranger.</h1>;
}

组件

React以“组件”的形式来组织整个代码。每个组件都是.js文件中的一个大写字母开头的function。例如,约定俗成每个React应用的组件为function App() {}

使用JavaScriptJSX编写组件,意味着每个组件都将包含:

  • 数据
  • 逻辑
  • 外观

image

每个组件都将return一段JSX代码,作为整个组件实际渲染的内容。

组件分解

分解组件的标准

一些其它的注意事项:

  • 每新建一个组件就会带来新的抽象,而抽象需要大量的精力来维护;
  • 用功能来精确命名组件,不要担心过长的名称;
  • 不要在一个组件的内部声明另一个组件。

组件的复用

我们可以在组件内部嵌套另一个组件。然而,为了组件的复用性考虑,我们最好使用插槽(组合)的方法来维护组件之间的关系。

使用与组合

道具

React中,组件组成了整个用户界面。“道具”是一种在组件之间传递信息的重要方法。

image

React中的道具由父组件向子组件单向传递。我们可以使用道具传递各种各样的变量。

image

由于道具由父组件拥有,因此接受道具的子组件永远不应该更改道具。这就是道具的不变性。要在子组件中更改道具的值,应该传入状态函数,并借助状态函数完成更改。

image

道具还可以作为上文提到的组件的API来使用。

使用道具作为API

使用道具

props参数传递

可以直接在JSX的标签中指定参数,并在子组件中使用默认的props参数来接收;

1
2
3
4
5
6
7
// in father component
return <Child value1="1" value2="2" />;
//
funtcion Child(props){
  //props.value1 : "1"
  //props.value2 : "2"
}

参数展开

可以在JSX的标签中指定多项参数,在子组件中对其进行展开接收。

1
2
3
4
5
6
7
// in father component
return <Child value1="1" value2="2" />;
//
funtcion Child({value1, value2}){
  //value1 : "1"
  //value2 : "2"
}

children参数

可以传递JSX中标签块头尾之间的元素。这些元素会被子组件用children参数接收。

1
2
3
4
5
6
return <Child><p>HelloWorld!</p></Child>;
//
funtcion Child({children}){
  return children;
  //<p>HelloWorld!</p>
}

组件与道具实战

一张个人资料卡片。由四种组件组成:

image

首先构造静态的头像、文字区域。

1
2
3
4
5
6
7
8
9
function Avatar() {
  return (
    <img
      className={"avatar"}
      src={"/absproxy/3000/avatar.jpg"}
      alt={"avatar"}
    />
  );
}
1
2
3
4
5
6
7
8
function Intro() {
  return (
    <div className={"data"}>
      <h1>Tanasa</h1>
      <p>A grey hair, different-eyed furry girl.</p>
    </div>
  );
}

接下来,我们有一个Skills数组用于构建Skill组件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
const Skills = [
  {
    text: "Catching Fish",
    color: "cyan",
    level: "intermediate",
  },
  {
    text: "Cook",
    color: "orange",
    level: "advanced",
  },
  {
    text: "Sewing",
    color: "gray",
    level: "intermediate",
  },
  {
    text: "Protect",
    color: "green",
    level: "beginner",
  },
];

我们会在SkillList组件中对Skills数组使用map方法,将每一个Skill对象映射给每一个Skill组件。

1
2
3
4
5
6
7
8
9
function SkillList() {
  return (
    <ul className={"skill-list"}>
      {Skills.map((skill) => (
        <Skill skillObj={skill} />
      ))}
    </ul>
  );
}

接下来,在Skill组件中主动接收SkillList传递的道具。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
function Skill({ skillObj }) {
  let emoji = null;
  if (skillObj.level === "advanced") emoji = "🚗";
  else if (skillObj.level === "intermediate") emoji = "🏍️";
  else if (skillObj.level === "beginner") emoji = "🚲";
  //根据字符串条件渲染emoji
  return (
    <li className={"skill"} style={{ backgroundColor: skillObj.color }}>
      <span>{skillObj.text}</span>
      <span>{emoji}</span>
    </li>
  );
}

最后,在App组件中包含并渲染上述组件。

1
2
3
4
5
6
7
8
9
function App() {
  return (
    <div className={"card"}>
      <Avatar />
      <Intro />
      <SkillList />
    </div>
  );
}

image