react组件

2021-12-27 REACT 大约 3 分钟

组件的可复用、独立、可组合特性可以让我们用多个组件实现完整的页面功能,进行更快速的项目开发。

react中组件分为两类:

  • 类组件;
  • 函数组件;

# 函数组件

使用js创建的并返回JSX的函数,称为函数组件。函数组件通常⽆状态,仅关注内容展示,返回渲染结果即可。

// 创建一个函数组件
function Hello() { 
  return ( 
    <div>这是我的第一个函数组件!</div> 
  ) 
} 
// 用函数名作为组件标签名
ReactDOM.render(<Hello />, document.getElementById('root'))
1
2
3
4
5
6
7
8

注意:

  • 函数名称必须以大写字母开头,使用大驼峰命名法;
  • 函数组件必须有返回值,表示该组件的结构;
  • 组件标签可以单闭合

相关信息

从React16.8开始引⼊了hooks,函数组件也能够拥有状态

# 类组件

使用ES6class关键字创建的组件称为类组件 。class组件通常拥有状态和⽣命周期,继承于Component,实现render⽅法。

// 类组件应该继承`React.Component`父类,从而可以使用父类中提供的方法和属性。
class Hello extends React.Component { 
  render() { 
    return <div>Hello Class Component!</div> 
  } 
} 
ReactDOM.render(<Hello />, root) 
1
2
3
4
5
6
7

注意:

  • 类名称也必须以大写字母开头使用大驼峰命名法
  • 类组件必须提供render()方法 。
  • render()方法必须有返回值,表示该组件的结构。

# 高阶组件

高阶组件本质上就是高阶函数,接收要包装的组件,返回增强后的组件。

  1. 创建一个函数,名称约定以 with 开头 。
  2. 指定函数参数,参数应该以大写字母开头(作为要渲染的组件)。
  3. 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回 。
  4. 在该组件中,渲染参数组件,同时将状态通过prop传递给参数组件。
  5. 调用该高阶组件,传入要增强的组件,通过返回值拿到增强后的组件,并将其渲染到页面中 。
// 创建一个高阶组件
function withMouse(WrappedComponent) { 
  // 创建类组件并返回
  return class MouseHoc extends React.Component {
    state = {
      x:0,
      y:0
    }
    
    render() {
      // 使用参数组件并传入状态参数;
      return <WrappedComponent {...this.state} /> 
    }
  } 
} 

// 创建组件 Position为要传入的另一个函数组件;
const MousePosition = withMouse(Position) 
 
// 渲染组件 
<MousePosition /> 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

注意

不要在 render ⽅法中使⽤ HOC,React 的 diff 算法(称为协调)使⽤组件标识来确定它是应该更 新现有⼦树还是将其丢弃并挂载新⼦树。 如果从 render 返回 的组件与前⼀个渲染中的组件相同(===),则 React 通过将 ⼦树与新⼦树进⾏区分来递归更新⼦树。 如果它们不相等,则 完全卸载前⼀个⼦树。

render() {
  // 每次调⽤ render 函数都会创建⼀个新的
  EnhancedComponent
  // EnhancedComponent1 !== EnhancedComponent2
  const EnhancedComponent = enhance(MyComponent);
  // 这将导致⼦树每次渲染都会进⾏卸载,和重新挂载的操作!
  return <EnhancedComponent />;
}
1
2
3
4
5
6
7
8

# 装饰器

⾼阶组件本身是对装饰器模式的应⽤,⾃然可以利⽤ES7中出现的 装饰器语法来更优雅的书写代码。

# 安装依赖

npm install -D @babel/plugin-proposal-decorators react-app-rewired customize-cra
1

# 添加配置文件

// config-overrides.js

//配置完成后记得重启下
const { addDecoratorsLegacy, override } = require("customize-cra");

module.exports = override(
  //配置装饰器
  addDecoratorsLegacy()
)
1
2
3
4
5
6
7
8
9

# 修改启动脚本

"scripts": {
-  "start": "react-scripts start",
+  "start": "react-app-rewired start",
-  "build": "react-scripts build",
+  "build": "react-app-rewired build",
+  "test": "react-app-rewired test",
+  "eject": "react-app-rewired eject"
},
1
2
3
4
5
6
7
8

# 使用

const Bar = (Child) => (props) => {
  return (<div>
    <h1>BAR</h1>
    <Child {...props} />
  </div>)
}

export default Bar;
1
2
3
4
5
6
7
8
import React, { Component } from 'react';
import Bar from './bar';

// 使用装饰器
@Bar
class Foo extends Component {
  render() {
    return (<div>Foo</div>)
  }
}

export default Foo;
1
2
3
4
5
6
7
8
9
10
11
12
import React from 'react';
import Foo from './views/foo';

function App() {
  return (
    <div className="App">
      <Foo />
    </div>
  );
}

export default App;
1
2
3
4
5
6
7
8
9
10
11
12

::: into

  • 装饰器必须return一个函数,不能直接返回一个jsx

    // 正确
    const Bar = (Child) => (props) => {
      return (<Child {...props} />)
    }
    
    // 错误
    const Bar = (Child) => {
      return (<Child {...props} />)
    }
    
    export default Bar;
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
  • 被装饰的组件,要以组件的方式使用< Child />不能{ Child }

  • 装饰器只能⽤在class上。

  • 多个装饰器,执⾏顺序从下往上。

:::

上次编辑于: 2023年7月4日 09:36