劫持react组件

劫持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"));

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

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值