首页 文章详情

React17在我看来是这样的

前端大神之路 | 1225 2021-03-14 08:22 0 0 0
UniSMS (合一短信)

本文适合觉得React难学,或者想重头系统化学习React的小伙伴。

如果这篇文章有触动到你,欢迎关注前端早茶,与广东靓仔携手共同进阶~

作者:广东靓仔

一、前言

本文基于开源项目:

https://github.com/facebook/react

    广东靓仔总结下自己这几年对学习前端框架的一些想法,顺便讲讲React17带来的改变引起的一些个人想法。 
    在我们学习一门前端框架的时候,广东靓仔觉得官方文档一定是最好的学习资料。有些小伙伴可能把官方文档当作入门指南,然后再找其他学习资料去深度学习。广东靓仔觉得有点舍近求远了,官方文档一定是开发人员尽可能去写全、写精的。我们应该仔细的去阅读,而不是粗略看了一遍,然后找各种文章去阅读学习。
    在这里广东靓仔可以很负责的说一句,市面上80%免费的文章,基本都是基于官方文档来写的。广东靓仔的文章也是如此,只不过是加了点自己的思考。

    React官方文档写得特别好,还带着我们去领悟它的设计模式。

1.1 没有React基础可以开始用React17吗?

在React16.8版本引入了hook以来,React的学习成本就已经降低了很多了,我们可以通过函数式编程来开发我们的应用。React以前就像一艘“航母”一样,大而全。正因“全”因此我们的学习成本自然就高。有了hook我们使用函数组件开发,上手难度自然降低了很多。

二、React 17 带来了哪些改变

    React17.0.1版本相对与16.8版本本身没有增加新特性,只是做了一些补充。17版本更像一个 基石 ,为什么这么说呢?细心的小伙伴们会发现官方描述了这么一句话:“React v17 开启了 React 渐进式升级的新篇章”。这句话我看出了雄心勃勃,后续 18、19 等的更新版本一定是以17这个“基石”来开启新篇章。

这里列举让广东靓仔眼前一亮的两点:

1、新的 JSX 转换逻辑

2、事件系统重构


当然React17也有其他的更新,大家有兴趣可以去看官方文档。

三、重构 JSX 转换逻辑

React17之前我们如果这样写,代码如下:

function MyComponent() {
  return <p>前端早茶</p>
}

页面是会报错的,why?

上一篇文章有讲到React 中对 JSX 代码的转换依赖的是 React.createElement 这个函数。有兴趣可以回头看下上一篇文章。

因此在写JSX的时候,是一定要在头部引入React的,代码如下:

import React from 'react';
function MyComponent() {
  return <p>前端早茶</p>
}
React17之后我们在使用JSX,不再需要引入import React from 'react'; 
React17中编译器会自动帮我们引入 JSX 的解析器的,例如:
function MyComponent() {
  return <p>前端早茶</p>
}

这个代码最后会被编译器转换为:

import {jsx as _jsx} from 'react/jsx-runtime';
function MyComponent() {
  return _jsx('p', { children'前端早茶' });
}
react/jsx-runtime 中的 JSX 解析器帮我们完成了JSX的编译工作,很明显降低了我们的学习成本。如果有的小伙伴一开始就是从React17开始学习的,我们无感知的使用到它的方便。
关于这块的内容,详细可以看看如下内容:

https://github.com/reactjs/rfcs/blob/createlement-rfc/text/0000-create-element-changes.md#motivation

四、事件系统重构

React17版本中事件系统重构可以分为两块来看:

  • 放弃document 来做事件的中心化管控
  • 放弃事件池


    4.1 卸掉历史包袱

    React之前是将所有事件冒泡到 document 来实现对事件的中心化管控,17版本放弃 document 来做事件的中心化管控。
    why?因为有些时候合成事件虽然在 React 事件体系下的冒泡被阻止了,但是并不能够阻止原生 DOM 事件的冒泡。
    React17中,事件管控相关的逻辑被转移到了每个 React 组件自己的容器 DOM 节点中,比如我们常写的在 ID 为 root 的 DOM 节点下挂载了一个 React 组件,代码如下:
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

之后React 组件就只能自己管理自己的东东了,无法再影响到全局了。

    4.2 拥抱新潮流

    React 之前,合成事件对象都是被放进“事件池”统一管理,为了能够对事件对象的复用,提高性能。细心的小伙伴会发现,既然考虑到复用,事件处理函数执行完成后,合成事件对象内部的所有属性都会被置空。
    那么问题来了,如果事件执行完成,我们想获取事件对象呢?

    广东靓仔找来了官方的代码,来说明:

function handleChange(e{
  // This won't work because the event object gets reused.
  setTimeout(() => {
    console.log(e.target.value); // Too late!
  }, 100);
}
异步执行的 setTimeout 回调会在 handleChange 这个事件处理函数执行完毕后执行,因此它拿不到想要的那个事件对象 e了。

要想获取的话,我们就需要使用e.persist() ,代码如下:

function handleChange(e{
  // Prevents React from resetting its properties:
  e.persist();
  setTimeout(() => {
    console.log(e.target.value); // Works
  }, 100);
}
React 17在研发体验上考虑比较多,官方放弃事件池,为每一个合成事件创建新的对象。所以之后我们不再需要编写 e.persist(),也可以随时随地访问我们想要的事件对象。

五、总结

    在我们阅读完官方文档后,我们一定会进行更深层次的学习,比如看下框架底层是如何运行的,以及源码的阅读。
    这里广东靓仔给下一些小建议:
  • 在看源码前,我们先去官方文档复习下框架设计理念、源码分层设计
  • 阅读下框架官方开发人员写的相关文章
  • 借助框架的调用栈来进行源码的阅读,通过这个执行流程,我们就完整的对源码进行了一个初步的了解
  • 接下来再对源码执行过程中涉及的所有函数逻辑梳理一遍

关注我,一起携手进阶

如果这篇文章有触动到你,欢迎关注前端早茶,与广东靓仔携手共同进阶~

good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter