zl程序教程

您现在的位置是:首页 >  工具

当前栏目

react:创建组件的几种方式与区别

组件React 区别 创建 方式 几种
2023-09-27 14:27:09 时间

组件概念

接收唯一带有数据的 “props”(代表属性)对象与并返回一个 React 元素。
react组件包括函数组件和 class 组件:

创建组件三种方式

  1. 函数式定义的无状态组件
  2. es5 原生方式 React.createClass 定义的组件(有缺点不太用了)
  3. es6 形式的 extends React.Component 定义的组件

1、函数式定义的无状态组件

为了创建纯展示组件,这种组件只负责根据传入的props来展示,不涉及到要state状态的操作。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

特点:

  1. 组件不会被实例化,整体渲染性能得到提升
    因为组件被精简成一个render方法的函数来实现的,由于是无状态组件,所以无状态组件就不会在有组件实例化的过程,无实例化过程也就不需要分配多余的内存,从而性能得到一定的提升。
  2. 组件不能访问this对象
    无状态组件由于没有实例化过程,所以无法访问组件this中的对象,例如:this.ref、this.state等均不能访问。若想访问就不能使用这种形式来创建组件
  3. 组件无法访问生命周期的方法
    因为无状态组件是不需要组件生命周期管理和状态管理,所以底层实现这种形式的组件时是不会实现组件的生命周期方法。所以无状态组件是不能参与组件的各个生命周期管理的。
  4. 无状态组件只能访问输入的props,同样的props会得到同样的渲染结果,不会有副作用

注意: 组件名称必须以大写字母开头。自从出现了hook,我们就不叫无状态组件了,更准确的应该叫函数组件

2、es5 原生方式 React.createClass 定义的组件

不讲了,已经不怎么用了

3、es6 形式的 extends React.Component 定义的组件

计时器例子:

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
1. 当 <Clock /> 被传给 ReactDOM.render()的时候,React 会调用 Clock 组件的构造函数。因为 Clock 需要显示当前的时间,所以它会用一个包含当前时间的对象来初始化 this.state。我们会在之后更新 state。

2. 之后 React 会调用组件的 render() 方法。这就是 React 确定该在页面上展示什么的方式。然后 React 更新 DOM 来匹配 Clock 渲染的输出。

3. 当 Clock 的输出被插入到 DOM 中后,React 就会调用 ComponentDidMount() 生命周期方法。在这个方法中,Clock 组件向浏览器请求设置一个计时器来每秒调用一次组件的 tick() 方法。

4. 浏览器每秒都会调用一次 tick() 方法。 在这方法之中,Clock 组件会通过调用 setState() 来计划进行一次 UI 更新。得益于 setState() 的调用,React 能够知道 state 已经改变了,然后会重新调用 render() 方法来确定页面上该显示什么。这一次,render() 方法中的 this.state.date 就不一样了,如此以来就会渲染输出更新过的时间。React 也会相应的更新 DOM。

5. 一旦 Clock 组件从 DOM 中被移除,React 就会调用 componentWillUnmount() 生命周期方法,这样计时器就停止了。

注意:

  • 不要直接修改 State,而是应该使用 setState()
  • setState() 可能是异步的

一些其他组件

高阶组件

高阶组件是参数为组件,返回值为新组件的函数。
解决了mixin 产生的几个问题:

  • 破坏了原有组件的封装
  • 命名冲突
  • 增加复杂性

构建一个简单的hoc,感觉有点像回调函数诶

function hello (){
    console.log("hello i  love react ")
}


function hoc(fn){
    return ()=>{
          console.log("first");
            fn();
          console.log("end");
    }
}


hello = hoc(hello);

hello();

实现高阶组件的方法:

  • 属性代理:高阶组件通过呗包裹的React组件来操作props
  • 反向继承:高阶组件继承于被包裹的React组件

属性代理:

import React,{Component} from 'react';

const MyContainer = (WraooedComponent) => {
    class extends Component {
        render(){
            return <WrappedComponent {...this.props} />
        }
    }
}
import React,{Component} from 'react';

class MyComponent extends Component{
    //...
}

export default MyContainer(MyComponent);

调用顺序didmount ->HOC didmount ->(HOCs didmount)->(HOCs will unmount)->HOC will unmount -> unmount

反向继承:

const MyContainer = (WrappedComponent)=>{
    class extends WrappedComponent {
        render(){
            return super.render();
        }
    }
}
import React from 'react'

function HOCFactoryFactory(...params){
    return function HOCFactory(WrappedComponent){
        return class HOC extends Component{
            render(){
                return <WrappedComponent {...this.props} />
            }
        }
    }
}
// 使用
HOCFactoryFactory(params)(WrappedComponent)
// or
@HOCFactoryFactory(params)
class WrappedComponent extends React.Component{}

调用顺序didmount -> HOC didmount ->(HOCs didmount) -> will unmount ->HOC will unmount ->(HOCs will unmount)

hook

专门拿出一篇博客来说吧 https://blog.csdn.net/weixin_43972437/article/details/105326274

一些其他概念

props

当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)转换为单个对象传递给组件,这个对象被称之为 “props”。