劫持react组件

news/2024/7/24 13:34:45 标签: react.js, 前端, 前端框架

劫持props

假设我们有一个原组件,它接收一个 name prop,并显示一个问候语:

// 原组件
function Greeting(props) {
  return <h1> Hello, {props.name}! </h1>;
}

我们可以定义一个高阶组件,它可以通过 props 传递一个 color prop 给原组件,让原组件的文字颜色变化。同时,它也可以修改原组件的 name prop,让它变成大写。这样,我们就劫持了原组件的 props。

// 高阶组件
function withColor(WrappedComponent) {
  return function (props) {
    // 劫持 props
    const newProps = { ...props, name: props.name.toUpperCase() };
    // 劫持 render
    const style = { color: props.color };
    return (
      <div style={style}>
        <WrappedComponent {...newProps} />
      </div>
    );
  };
}

然后,我们可以使用高阶组件来创建一个新的组件,它接收一个 color prop,并传递给原组件:

// 劫持后的组件
const ColoredGreeting = withColor(Greeting);

ReactDOM.render(
  <ColoredGreeting name="Alice" color="red" />,
  document.getElementById("root")
);

这样,我们就得到了一个显示红色文字,并且名字是大写的问候语组件。

劫持state

假设我们有一个原组件,它接收一个 count prop,并显示一个计数器:

// 原组件
function Counter(props) {
  return (
    <div>
      <h1> Count: {props.count} </h1>
      <button onClick={props.increment}> + </button>
      <button onClick={props.decrement}> - </button>
    </div>
  );
}

我们可以定义一个高阶组件,它可以管理原组件的 count 状态,并提供 increment 和 decrement 方法给原组件,让原组件可以更新状态。这样,我们就劫持了原组件的 state。

// 高阶组件
function withState(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = { count: 0 };
      this.increment = this.increment.bind(this);
      this.decrement = this.decrement.bind(this);
    }
    increment() {
      this.setState((state) => ({ count: state.count + 1 }));
    }
    decrement() {
      this.setState((state) => ({ count: state.count - 1 }));
    }
    render() {
      // 劫持 state
      const newProps = {
        ...this.props,
        count: this.state.count,
        increment: this.increment,
        decrement: this.decrement,
      };
      return <WrappedComponent {...newProps} />;
    }
  };
}

然后,我们可以使用高阶组件来创建一个新的组件,它不需要接收任何 prop,因为它的状态已经由高阶组件管理了:

// 劫持后的组件
const StatefulCounter = withState(Counter);

ReactDOM.render(<StatefulCounter />, document.getElementById("root"));

这样,我们就得到了一个可以自增和自减的计数器组件。

劫持render

假设我们有一个原组件,它接收一个 title prop,并显示一个标题:

// 原组件
function Title(props) {
  return <h1> {props.title} </h1>;
}

我们可以定义一个高阶组件,它可以在原组件的外面添加一个边框,修改原组件的样式,或者根据条件决定是否渲染原组件。这样,我们就劫持了原组件的 render。

// 高阶组件
function withBorder(WrappedComponent) {
  return function (props) {
    // 劫持 render
    const style = { border: "1px solid black", padding: "10px" };
    return (
      <div style={style}>
        <WrappedComponent {...props} />
      </div>
    );
  };
}

function withStyle(WrappedComponent) {
  return function (props) {
    // 劫持 render
    const style = { color: "red", fontSize: "24px" };
    return <WrappedComponent {...props} style={style} />;
  };
}

function withCondition(WrappedComponent) {
  return function (props) {
    // 劫持 render
    if (props.title.length > 10) {
      return <WrappedComponent {...props} />;
    } else {
      return null;
    }
  };
}

然后,我们可以使用高阶组件来创建一个新的组件,它会根据不同的高阶组件有不同的渲染效果:

// 劫持后的组件
const BorderedTitle = withBorder(Title);
const StyledTitle = withStyle(Title);
const ConditionalTitle = withCondition(Title);

ReactDOM.render(
  <div>
    <BorderedTitle title="Hello, world!" />
    <StyledTitle title="Hello, world!" />
    <ConditionalTitle title="Hello, world!" />
    <ConditionalTitle title="Hello, everyone!" />
  </div>,
  document.getElementById("root")
);

这样,我们就得到了一个有边框的标题,一个红色字体的标题,和一个只在标题长度大于10时才显示的标题。

劫持生命周期

假设我们有一个原组件,它接收一个 data prop,并显示一个列表:

// 原组件
function List(props) {
  return (
    <div>
      <ul>
        {props.data.map((item, index) => {
          return <li key={index}>{item}</li>;
        })}
      </ul>
    </div>
  );
}

我们可以定义一个高阶组件,它可以在原组件的 componentDidMount 和 componentWillUnmount 方法中执行一些操作,比如发送请求,设置定时器,添加事件监听等。这样,我们就劫持了原组件的生命周期。

// 高阶组件
function withLifecycle(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = { data: [] };
      this.fetchData = this.fetchData.bind(this);
      this.handleResize = this.handleResize.bind(this);
    }
    componentDidMount() {
      // 劫持生命周期
      this.fetchData();
      this.timer = setInterval(this.fetchData, 5000);
      window.addEventListener("resize", this.handleResize);
    }
    componentWillUnmount() {
      // 劫持生命周期
      clearInterval(this.timer);
      window.removeEventListener("resize", this.handleResize);
    }
    fetchData() {
      fetch("/api/data")
        .then((data) => {
          this.setState({ data: data });
        })
        .catch((error) => {
          console.error(error);
        });
    }
    handleResize() {
      console.log("Window resized");
    }
    render() {
      return <WrappedComponent {...this.props} data={this.state.data} />;
    }
  };
}

然后,我们可以使用高阶组件来创建一个新的组件,它不需要接收任何 prop,因为它的数据和行为已经由高阶组件管理了:

// 劫持后的组件
const LifecycleList = withLifecycle(List);

ReactDOM.render(<LifecycleList />, document.getElementById("root"));

这样,我们就得到了一个可以自动更新数据,并且响应窗口大小变化的列表组件。


http://www.niftyadmin.cn/n/1004226.html

相关文章

【云原生丶Kubernetes】从应用部署的发展看Kubernetes的前世今生

在了解Kubernetes之前&#xff0c;我们十分有必要先了解一下应用程序部署的发展历程&#xff0c;下面让我们一起来看看&#xff01; 应用部署的发展历程 我们先来看看应用程序部署的3个阶段&#xff1a;从物理机部署到虚拟机部署&#xff0c;再到容器化部署&#xff0c;他们之…

Linux下查看共享文件(so库)的编译是32位还是64位

方法一 采用file查看&#xff1a; file 命令可以用于查看文件的类型。它会根据文件的内容进行分析&#xff0c;给出详细的文件类型信息。 如&#xff1a; file libQtCore.so 显示如下 libQtCore.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamica…

Java基础---接口和抽象类的区别

目录 访问修饰符不同 职责不同 接口Interface 抽象类abstract class 访问修饰符不同 接口和抽象类&#xff0c;最明显的区别就是接口只是定义了一些方法而已&#xff0c;在不考虑Java8中default方法情况下&#xff0c;接口中是没有实现的代码的抽象类中的抽象方法可以有pub…

八数码、解华容道(bfs,全局择先,A*搜索)

【问题描述】 题目6&#xff1a;数阵问题 每个局面是三行三列的数字方阵&#xff0c;每个位置为0-8的一个数码且互不相同&#xff0c;求从初始局面&#xff08;自己设定&#xff09;如何“最快”移动到终止局面&#xff08;自己设定&#xff09;。 移动规则&#xff1a;每次只…

【推荐】win 安装 rust 1.70

目录 一、下载二、安装先决条件MinGW三、安装Rust四、配置国内镜像五、检查是否安装成功五、参考文章 一、下载 官网地址&#xff1a;https://www.rust-lang.org/zh-CN/ 二、安装先决条件MinGW win 安装 C运行环境 - MinGW 三、安装Rust 3.1首先设置安装路径和环境变量 配…

利用jmeter测试java请求

jmeter和loadrunner一样包含了测试脚本开发、测试执行、以及测试结果统计三个部分。只是jmeter没有脚本开发工具&#xff0c;因此测试java请求的脚本选择在eclipse中进行。 首先介绍如何用eclipse编写接口性能测试脚本。 针对"Java请求"类型的测试&#xff0c;需要…

管理类联考——英语——趣味篇——词根词汇——按频次分类——高频词汇——List1

优化原书记忆方法&#xff0c;轻松搞定考研单词 摒弃了传统的以字母顺序排序的方法&#xff0c;结合近20年考研真题&#xff0c;通过电脑搜索等方法对核心词进行科学统计&#xff0c;将核心词有机地分为高频词汇、常考词汇、中频词汇、低频词汇等4大部分&#xff0c;同时还补充…

分析Android高工招聘市场技术需求,学习高级技术技巧

作为一名高级 Android 开发工程师&#xff0c;需要具备以下技术和能力&#xff1a; 广泛的 Android 开发知识&#xff1a; 深入理解 Android 框架、组件和 API&#xff0c;并能熟练运用它们进行应用开发。熟悉 Android 应用的生命周期、UI 布局、多线程编程等。 扎实的 Java…