Appearance
组件化开发
组件化思想的应用
- 有了组件化的思想,我们在之后的开发中就要充分的利用它。
- 尽可能的将页面拆分成一个个小的、可复用的组件。
- 这样让我们的代码更加方便组织和管理,并且扩展性也更强。
组件分类:
- 根据组件的定义方式,可以分为:函数组件 (Functional Component ) 和类组件 (Class Component);
- 根据组件内部是否有状态需要维护,可以分成:无状态组件 (Stateless Component ) 和有状态组件 (Stateful Component);
- 根据组件的不同职责,可以分成:展示型组件 (Presentational Component) 和容器型组件 (Container Component);
大体可以用一个公式表达
UI = F(state)
1
2
2
以将 UI 切分成一些独立的、可复用的部件,这样你就只需专注于构建每一个单独的部件
组件从概念上类似于 JavaScript 函数。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素
React 的组件相对于 Vue 更加的灵活和多样,按照不同的方式可以分成很多类组件:
- 根据组件的定义方式,可以分为:函数组件 (Functional Component ) 和类组件 (Class Component);
- 根据组件内部是否有状态需要维护,可以分成:无状态组件 (Stateless Component ) 和有状态组件 (Stateful Component);
- 根据组件的不同职责,可以分成:展示型组件 (Presentational Component) 和容器型组件 (Container Component);
class 组件
类组件的定义有如下要求:
组件的名称是大写字符开头(无论类组件还是函数组件)
类组件需要继承自 React.Com-onent
类组件必须实现 render 函数
在 ES6 之前,可以通过 create-react-class 模块来定义类组件,但是目前官网建议我们使用 ES6 的 class 类定义。
使用 class 定义一个组件:
- constructor 是可选的,我们通常在 constructor 中初始化一些数据;
- this.state 中维护的就是我们组件内部的数据;
- render() 方法是 class 组件中唯一必须实现的方法;
jsx
import React , { Componet } from "react";
// 基于类的组件
export class Welcome2 extends Componet {
constructor(props){
super(props);
this.state = {
date: new Date()
}
}
// 组件挂载完成之后执行
componentDidMount(){
this.timer = setInterval(()=>{
// 更新state,不能调用this.state
this.setState({
date: new Date()
})
},1000)
}
componentWillUnmount(){
clearInterval(this.timer)
}
render() {
return <div>{data.toLocaleTimeString()}</div>;
}
}
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
render 函数
- 当 render 被调用时,它会检查 this.props 和 this.state 的变化并返回以下类型之一:
- React 元素:
- 通常通过 JSX 创建。
- 例如,
<div />会被 React 渲染为 DOM 节点,<MyComponent />会被 React 渲染为自定义组件; - 无论是
<div />还是<MyComponent />均为 React 元素。
- 数组或 fragments:使得 render 方法可以返回多个元素。
- Portals:可以渲染子节点到不同的 DOM 子树中。
- 字符串或数值类型:它们在 DOM 中会被渲染为文本节点
- 布尔类型或 null:什么都不渲染。
函数组件
- 函数组件是使用 function 来进行定义的函数,只是这个函数会返回和类组件中 render 函数返回一样的内容。
- 函数组件有自己的特点(当然,后面我们会讲 hooks,就不一样了):
- 没有生命周期,也会被更新并挂载,但是没有生命周期函数;
- 没有 this(组件实例);
- 没有内部状态(state);
- 我们来定义一个函数组件
- 函数组件接收一个单一的 props 对象并返回了一个 React 元素
jsx
import React, { useState, useEffect } from "react";
export function FunctionComponet(props) {
const [date, setDate] = useState(new Date());
useEffect(() => {
// 相当于componentDidMounet,componetWillUnmount的集合
const timer = setInterval(() => {
setDate(new Date());
}, 1000);
return () => clearInterval(timer);
}, []);
return (
<div>
<h3>FunctionComponet</h3>
<h3>{date.toLocaleTimeString()}</h3>
</div>
);
}
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
组件渲染
- React 元素不但可以是 DOM 标签,还可以是用户自定义的组件
- 当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)转换为单个对象传递给组件,这个对象被称之为 props
- 组件名称必须以大写字母开头
- 组件必须在使用的时候定义或引用它
- 组件的返回值只能有一个根元素
jsx
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="hello" />;
ReactDOM.render(
element,
document.getElementById('root')
);
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
React 只会更新必要的部分
- React DOM 首先会比较元素内容先后的不同,而在渲染过程中只会更新改变了的部分。
- 即便我们每秒都创建了一个描述整个 UI 树的新元素,React DOM 也只会更新渲染文本节点中发生变化的内容