当前位置:首页 > 技术分析 > 正文内容

函数式组件与类组件有何不同

ruisui884周前 (05-23)技术分析19

前言

React 中最关键的知识点就是 组件,在 React 16.8 之前(还没有 Hooks 前),我们的应用大多写成 Class 组件,因为 Class 组件有生命周期,能控制状态(state)。但函数式组件只能默默站在后面,说自己是木偶组件(也叫无状态组件),传来 props,展示UI

以下文字都基于有了 Hooks 后

正文

函数式组件和类组件之间是否有什么根本上的区别?

函数式组件捕获渲染时的值

具体可以看这篇文章:函数式组件与类组件有何不同?

因为在 React 中 props 是不可变(immutable)的,它们永远不会改变。然而,this 是可变(mutable)的

事实上,这就是类组件 this 存在的意义。React 本身会随着时间的推移而改变,以便你可以在渲染方法以及生命周期方法中得到最新的实例

函数式组件会捕获当前状态下的值,如果你使用定时器改变当前值的状态,那函数式组件显示的还是原来的值,而不是最新值。而类组件会一直获取最新值

只要一渲染,函数式组件就会捕获当前的值。而类组件即使渲染了,但是它的 this 会指向最新的实例

类组件

可以看线上Demo

class ClassDemo extends React.Component {
  state = {
    value: ""
  };

  showMessage = () => {
    alert("最新值为 " + this.state.value);
  };

  handleMessageChange = (e) => {
    this.setState({ value: e.target.value });
  };

  handleClick = () => {
    setTimeout(this.showMessage, 3000);
  };

  render() {
    return (
      <div>
        <input value={this.state.value} onChange={this.handleMessageChange} />
        <button onClick={this.handleClick}>点击</button>
      </div>
    );
  }
}

这样的结果是点击后获取到最新的值,而不是 3 秒前的值。为什么?因为 this 可变,3 秒之后执行 alert("最新值为 " + this.state.value)。 this.state.value 指向最新的值

如果类组件如果想保存原来的值该怎么做?

一、调用事件之前读取this.props

可以看线上Demo

showMessage = (value) => {
    alert("最新值为 " + value);
};

handleClick = () => {
    const { value } = this.state;
    setTimeout(() => this.showMessage(value), 3000);
};

可以解决,但点击时获取到当前的 user,再传递给 this.showMessage,这样,即使 3 秒之后也是原来的值

缺点:每次都要从 this.props 中拿值,如果数据一多,写起来不符合人性

二、在构造函数中绑定方法

可以看线上Demo

constructor(props) {
    super(props);
    this.showMessage = this.showMessage.bind(this);
    this.handleClick = this.handleClick.bind(this);
}

这个方法解决不了问题。我们的问题是我们从 this.props 中读取数据太迟了—— 读取时已经不是我们所需要使用的上下文

三、利用闭包

把方法写进 render 中,这样每次渲染时就能捕获住当时所用的 props 或者 state

可以看线上Demo

class ClassDemo extends React.Component {
  state = {
    value: ""
  };

  render() {
    const { value } = this.state;

    const showMessage = () => {
      alert("最新值为 " + value);
    };

    const handleMessageChange = (e) => {
      this.setState({ value: e.target.value });
    };

    const handleClick = () => {
      setTimeout(showMessage, 3000);
    };
    return (
      <div>
        <input value={this.state.value} onChange={handleMessageChange} />
        <button onClick={handleClick}>点击</button>
      </div>
    );
  }
}

但是这个方法很蠢,这个写法和函数式组件有什么区别呢?还不如用函数式组件呢

函数式组件如果想保存最新的值呢

使用 useRef 保存最新的值,让组件获得最新的值

function MyComponent() {
  const ref = useRef(null);
}

首先,ref 与实例都扮演同样的角色,ref 对象是一个有 current 属性的一个容器

上次的例子我们用函数式组件就可以这样写:

const FunctionDemo = () => {
  const [value, setValue] = useState("");

  const refValue = useRef("");

  const showMessage = () => {
    alert("最新值为 " + refValue.current);
  };

  const handleMessageChange = (e) => {
    setValue(e.target.value);
    refValue.current = e.target.value;
  };

  const handleClick = () => {
    setTimeout(showMessage, 3000);
  };

  return (
    <div>
      <input value={value} onChange={handleMessageChange} />
      <button onClick={handleClick}>点击</button>
    </div>
  );
};

可以看线上Demo

这里笔者提出两个疑问:

  • 为什么 ref 能保存住最新的值?
  • 为什么函数式组件会捕获,类组件不会呢?

后续文章会给出笔者的回答

参考资料

  • 函数式组件与类组件有何不同?

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/4273.html

标签: bindmessage
分享给朋友:

“函数式组件与类组件有何不同” 的相关文章

git的几种分支模式

编写代码,是软件开发交付过程的起点,发布上线,是开发工作完成的终点。代码分支模式贯穿了开发、集成和发布的整个过程,是工程师们最亲切的小伙伴。那如何根据自身的业务特点和团队规模来选择适合的分支模式呢?本文分享几种主流 Git 分支模式的流程及特点,并给出选择建议。分支的目的是隔离,但多一个分支也意味着...

10分钟搞定gitlab-ci自动化部署

gitlab-ci 是持续集成工具/自动化部署工具,类似 jenkins。持续集成 是将代码集成到共享存储库并尽可能早地自动构建/测试每个更改的实践 - 通常一天几次。概述在编码完成时都会进行打包发布过程,如果每次都手动操作这一步骤就会浪费时间,效率低下。所以就有了持续集成。准备事项请提前安装以下软...

VUE 技术栈

官网链接:https://cn.vuejs.org/什么是vue:渐进式JavaScript 框架vue-cli链接:https://cli.vuejs.org/vue-cli安装:npm install -g @vue/clivue -V创建一个项目:vue create xxxxxx模版语法:文...

尤雨溪:细聊 Vue 的现在与未来

大家好,我是 Echa。创作不易,喜欢的老铁们转发加个关注,点个赞,速速收藏,谢谢!另外咱们一起回顾一下Vue 优秀开源项目:12个又简单又实用的开源项目及组件推荐13个又热门又实用的Vue开源宝典库推荐7个Vue 3的高颜值UI组件库分享15个基于Vue3.0全家桶的优秀开源项目推荐10个基于Vu...

微信正开发“应用号”取代手机应用

长江商报消息用户只需关注公众号,不必下载APP就可获得相同体验本报讯(记者 陈妮希)昨日,2016微信公开课PRO版在广州举行,腾讯公司高级执行副总裁、微信事业群总裁张小龙首次公开演讲,并透露微信正在开发“应用号”,将应用和订阅号相结合。现场,微信团队还首次发布了腾讯生物识别标准“TENCENTSO...

一篇文章搞懂同步与异步、阻塞与非阻塞

要想掌握好Java NIO需要涉及了解同步与异步、阻塞与非阻塞,本文通过相关例子让你深入理解其本质@mikechen阻塞阻塞与非阻塞是对同一个线程来说的,在某个时刻,线程要么处于阻塞,要么处于非阻塞。阻塞调用是指调用结果返回之前,当前线程会被挂起,调用线程只有在得到结果之后才会返回。举一个例子:当一...