目录

React 组件

【资料】组件化开发的演变

创建 React 组件

SOLID 原则(基本上都是源自资料)

组件的数据流

组件的生命周期

高阶组件

【资料】装饰者模式


正常操作,正常分析,大家好,我是D1N910。

在大约两年前,我购买了 腾讯课堂【NEXT】一线大厂 React 实践宝典 这门课。

因为我一直基本上是使用Vue来进行前端页面的开发,但是一直没有时间去实践看完。 两年没去看了,真的很惭愧,时间,唉,过得真快啊。

为了在这门课过期之前看完,所以我要抓紧时间学完了。

本系列的专栏记录了我学习 一线大厂React实践宝典  的笔记。

下面的内容版权归属是  腾讯课堂【NEXT】一线大厂 React 实践宝典 这门课。

当然,如果我微不足道的笔记也算是我自己的版权,那么也是有我的小小一份。

你可以用来学习 React。

但是如果你用来商业化盈利,请先获得  腾讯课堂【NEXT】一线大厂 React 实践宝典 制作方的许可。

BTW,作为挖坑狂魔,如果这篇专栏没有更新,那么当我没说过。

这是一个系列的文章,如果你没有看过前面的内容,那么建议你先看一看

这是一个自己的约定,五一,冲冲冲!

今天,拿下 《React 组件》这个战壕,能够到达总体进度,如果一不小心把 《React 与 DOM》学完那就是血赚不亏,虽然不是同一个时间,但是是同一门课程,加油,奥利给,兄弟们,干了!

React 组件

这个课程每节都会有一个很有趣的小剧场,通过抛出一个问题然后接下来进行解答。

这边提了一个场景是,想要实现一个直播录音的功能,这个功能在其他页面已经有实现了,想要直接搬过来使用,但是代码杂糅,不是很容易直接搬过来使用。

通过将我们要用功能抽离为组件就可以比较方便地复用开发了。

组件与组件化

声明组件

概念:组件就像是一个函数。声明了一个属性,就相当于声明了一个组件。

ES6的组件声明的写法:

在之前和以后,我们都是会用这种基于 ES6 的 class 的写法。

每一个组件都会通过 render 方法返回一个 React 元素。

使用组件

常见的 React 元素有下面两种

1、基于 DOM 标签的 React 元素

const element = <div>Hello react</div>

2、基于自定义组件的 React 元素

const element = <Hello />

两者区别:自定义组件首字母大写

现在针对我们之前写的 Hello React 进行改造,把 Hello 抽离为组件。

之前的 Hello React

在项目的src文件下,新建一个文件夹名称叫 components,这个单词的意思是组件,一般来说,我习惯把项目的组件统一放到 components 里。

然后再在这个 components 文件夹下新建一个 Hello 文件夹,Hello 文件夹下新建 index.jsx,内容如下:

这里我们只需要引入 React,而不需要引入 ReactDom,因为我们只需要在这里制作出一个 React 组件,而不需要把它挂载到 Dom 节点上。

定义好了以后,我们需要在外部引入,直接 import 即可

本小节完毕, 仓库

https://github.com/D1N910/learn-react/tree/master/Chapter2/demo-1-hello-components

【资料】组件化开发的演变

web1.0 时代

页面代码主要是后端 JSP / PHP 生成的,前端改了功能后,如果想要看到效果,需要代码上传部署后才能够看到,非常影响效率。而且存在后端逻辑混在前端代码里的情况。对于后期来说,非常难以维护。

我本人不幸也算是有幸体验过这个开发流程,确实非常可怕。

后端 MVC 时代

这个时候 Web Server 的架构升级了,有了一些模版引擎,后端同学可以不用在页面模版中揉杂代码,只需要负责给模块返回对应的数据即可,前后端的职责相对明确一些了。但是还是要跑前面的流程。

Ajax 时代

Ajax时代,可以让前端更好地掌握主动权,这段时间比之前舒服多了。但是面临着会维护很多代码的情况。

React.js 带来的组件化时代

React 提供的前端组件化的概念,将很多代码切割好。

创建 React 组件

组件的属性

组件的属性-Props

属性的传递

const element = <Hello name="React" />

JSX 属性会被当成一个对象传到组件中。这里可以传入一个数字、字符串、对象、数组、函数、组件等等。

属性的接受

通过访问 this.props 可以获得组件的属性拿到值

Props特性

组件的数据流,Props 是只读的。只能从调用的一方传入,组件自己只能读取不能修改。

举例:

Main 组件 -> 传递 title 属性 -> Header 组件

Main 组件重新 render 的时候,才会传递新的 title 属性给到 Header 组件。

以我们之前的 Hello 组件 传值为例子

React 还提供了 children 的属性,这个属性能够让组件拿到父级传入的子元素。

改写父文件的 Hello 组件的书写方式,用包括子元素传递。子组件中通过 this.props.children 获取元素。

对 Props 进行类型检查

为什么需要类型检查?

因为 JavaScript 是一门弱类型的语言,允许变量类型做隐式转换,为了减少错误,我们可以在 React 中引入类型检查模块 —— 这样我们也可以很显而易见地知道我们的组件接受的参数类型是啥。

在组件中导入包

import PropTypes from 'prop-types';

(别忘了先 npm install 安装一下)

然后对我们的组件添加类型检测方法

这里的意思是检测传入的需要是字符串参数。

如果传参有误,会在控制台中抛出报错

所有能检测的类型在 prop-types 的 npm 包文档说明中

https://www.npmjs.com/package/prop-types

我们也可以通过配置 defaultProps 为 Props 定义默认值

函数定义组件

函数定义组件的例子

函数定义组件 与 类组件 的区别(内容大部分参考自原文)

1、函数式组件不会被实例化,整体渲染性能得到提升

函数式组件被精简为只有render方法, 没有实例化的过程,不需要分配多余的内容,让性能得到提升。

本身没有this,使用 Ref 等模块(后面会说)时与类组件也会有所区别。

2、函数式组件没有状态

函数式组件本身没有自己的内部状态 state,数据依赖与 props 的传入, 类似刚刚的

getH1(this.props),所以又称为无状态组件。

3、函数式组件无访问生命周期(后面会说)的方法

函数式组件是不需要组件生命周期管理,所以底层实现这种形式的组件时是不会实现组件的生命周期方法。

4、何时该使用函数式组件

函数式组件相比类组件,拥有更好的性能和更简单的职责,十分适合分割原本庞大的组件,未来 React 也会对函数式组件进行一系列的优化,譬如无意义检查和内存分配领域相关的优化。所以只有有可能,尽量使用函数式组件。

本小节完毕,相关代码如下

https://github.com/D1N910/learn-react/tree/master/Chapter2/demo-5-props

组件的组合与提取(设计组件)

组件的拆分

举例, 发现 Main 组件是由 组件 A、组件 B 和组件 C 组成的,其中发现组件 C 里面有一个组件 D。

这个自上而下的过程就是组件的 拆分 / 细化。

这个自下而上的过程就是组件的组合。

举例子,下面有一个普通的博客网页

提取组件后,结构长下面这样

最外层的父文件

header 组件

section 组件

最后查看网页能够正常展示结果~这样我们就完成了一个组件的拆分。

本小节结束,对应代码 如下

https://github.com/D1N910/learn-react/tree/master/Chapter2/demo-6-design-components

本节对应资料

SOLID 原则(基本上都是源自资料)

SOLID是五个面向对象编程的重要原则的缩写。另外,它也是每个开发者必备的基本知识。了解并应用这些原则能让你写出更优质的代码,变成更优秀的开发者。这个五个原则分别是:

  • SRP(单一责任原则)

  • OCP(开放封闭原则)

  • LSP(里氏替换原则)

  • ISP(接口分离原则)

  • DIP(依赖倒置原则)

单一责任原则(SRP)

* 一个类应该只有一个引起改变的原因

这个原则意味着一个类只应承担一个职责。如果我们的类承担的职责多于一个,那么我们的代码就具有高度的耦合性,任何对它的修改都会可能影响到多个地方,难以维护。遵循该原则可以降低代码的耦合性,提高代码的可维护性。

开闭原则(OCP)

* 软件实体(类,模块,函数等)应该对拓展开放,对修改封闭。

根据这一原则,一个软件实体能很容易地扩展新功能而不必修改现有的代码。这个原则的实现要点在于,使用合理的抽象构建一个实体的框架,功能细节能在实现中扩展。这个原则要求我们在设计软件的时候要预知未来可能发生的改变,合理的抽象实体框架,遵循该原则可以提高代码的可维护性和复用性。

里氏替换原则(LSP)

* 程序里的对象可以在不影响系统正常运作的条件下被它的子类实例所替换

简单来说,这个原则要求我们在继承一个父类的时候,不能修改父类中已经实现的方法。遵循该原则可以提高代码复用性和稳定性,降低系统出现问题的出现几率。

接口隔离原则(ISP)

* 一个类所定义的接口中不应存在该类不需要用到的方法

这个原则要求接口应当被设计成多个专用的接口而不是一个通用接口。不遵循这个原则意味着我们在实现一个接口的时候会依赖很多我们并不需要的方法,但又不得不去定义。遵循该原则可以降低代码的耦合度,后期更易于代码重构。

依赖倒转原则(DIP)

* 高层次的模块不应该依赖于低层次的模块,二者都应该依赖于抽象。抽象不应该依赖于细节,细节应该依赖于抽象。

这个原则简单来说,就是面向接口变成,它要求一个特定的类不应该直接依赖于另外一个类,但是可以依赖于这个类的抽象(接口)。使用该原则可以降低类与类的耦合度,提高我们代码的复用性。

总结

遵循 SOLID 原则可以帮助我们构建高质量、易扩展、易维护的软件系统,但过分的设计会让简单的问题复杂化,所以我们开发应当是从实际出发,灵活应用 SOLID 原则。

(手打了一遍,希望后面开发组件的时候能够多多用到)

组件的数据流

小剧场:一个复杂的组件的属性不能都依赖于外部吧,自己内部能够数据管理吗。React 有局部状态属性 State,可以在组件中单独进行维护。

组件的状态 - State

props 和 state 是组件中存储数据的主要方式。

首先来理解下什么是状态。为什么组件会拥有状态。

简而言之,组件就是一个状态机,不同的状态会带给组件不同的表现。

当一个组件拥有不同的状态( state )后,它就会展示不同的样式 (view)。

state -> view

比如我们有一个 Button 组件,它有状态1、状态2和状态3,分别代表着它是黄色、红色和绿色。

State 的声明和使用

下面的代码用 ES6 的写法,在 constructor 这个类的构造函数中,初始化了状态 this.state。

想要获取这个值,和获取props一样,可以使用 this.state.name

State 更新

以一个时钟组件为例子。

定一个 clock 属性,初始值是 new Date(),在函数 componentDidMount (马上就会介绍这个函数,现在先说明这是在组件挂载时会执行的方法)定义了一个定时器,每隔1s 去调用 this.setState() 方法更新 state 的 clock 属性,react 检测到了这个变化后,就会执行 render 函数重新去渲染更新视图。

相对于设置了定时器,我们也在 componentWillUnmount(组件将要卸载的时候) 定义了一个清除定时器的方法。

代码和效果如下

本小节完毕,相关代码在此

https://github.com/D1N910/learn-react/tree/master/Chapter2/demo-7-state

【资料】正确地使用组件局部状态

(又到了无情的打字机器人时间,内容基本上都是照搬自原文的,也有些是我个人的内容)

你使用State的姿势正确了吗?React 的核心思想是组件化的思想,而 State 正是组件中最重要的部分。组件状态的正确使用,可以帮助我们构造出可维护性更佳的组件。

正确地定义组件 State

State 是组件 UI 的数据模型,UI 的改变可以从 State 的变化中反映,而 State 中所有状态的改变都会引起组件 UI 的变化。一个变量是否应该被设置为状态,可以从以下两点进行判断:

  • 这个变量能否通过其他状态或者 props 计算得到?如果可以,则其不应该作为一个状态。

  • 该变量是否在 renader 方法中被使用,如果没有,其不该作为一个状态

简单来说,组件的状态一定要体现到 UI 的更新,且其值是唯一,无法通过计算得到。

不要直接更新 State

以下代码不会重新渲染组件:

// 错误

this.state.comment = 'Hello';

应当使用 setState 方法:

// 正确

this.setState({comment: 'Hello'});

值得一提的是,构造函数是唯一能够初始化 this.state 的地方

状态更新可能是异步的

React 可能会将多个 setState 调用合并为一个调用来提高性能,因此 this.props 和this.state 可能是异步更新的,你不应该靠他们的值来计算下一个状态。

例如,此代码可能无法更新计数器:

// 错误

this.setState({

counter: this.state.counter + this.props.increment

})

在这种强况下,我们使用 setState 方法时应当接收一个函数而不是一个对象。该函数将旧状态作为第一个参数,将此次更新被应用时的 props 作为第二个参数,如下:

// 正确

this.setState((prevState, props) => ({

counter: prevState.counter + props.increment

}))

关于 setState 的浅合并

当你调用 setState 方法时,React 将你提供的对象合并到当前状态。
例如我们的组件中包含多个状态:

constructor(props) {

super(props);

this.state = {

clock: new Date(),

name: 'Da Ben'

}

}

我们可以独立的更新其中一个状态属性:

componentDidMount() {

this.setState({

name: 'Da Ben 2'

})

}

这里的合并是浅合并,也就是说 this.setState({name}) 完整保留了 this.state.clock,但完全替换了 this.state.name。

状态提升

在 React 中,状态分享是通过将 state 数据提升至离需要这些数据的组件最近的父组件来完成的。这就是所谓的状态提升。

在 React 应用中,遵循单一数据源原则。简单来说,如果两个或者多个组件依赖于相同的数据,那么这些数据应当放到离需要它们的最近的父组件中,在应用中保持自上而下的数据流。这样的做法可以帮助我们更快的定位 bug,因为组件的状态只有组件自身可以操作,把可能产生 bug 的范围大大缩减了。

实际上就是放到 props 中。

组件的生命周期

小剧场

聪明男:刚刚我们有用到生命周期,那么 React 的生命周期具体是什么呢?

懵懂男:我理解为是一个组件从创建到销毁的过程。

聪明男:你理解得不错。生命周期主要分为三个,分别为组件创建时、组件更新时还有组件销毁时。并且 React 还为我们提供了对应的生命周期函数。

捧哏男:那我们什么时候需要用到这些生命周期函数呢?

聪明男:举个

【D1N910】一线大厂React实践宝典(二) React组件相关推荐

  1. 【D1N910】一线大厂React实践宝典(二) 课程引言+React开发环境

    目录 课程引言 React基本开发环境 搭建工程化React开发环境 开始你的 React 之旅 JSX 语法 混合 JavaScript 与 JSX 正常操作,正常分析,大家好,我是D1N910. ...

  2. React学习笔记(二) | 受控组件

    React组件 目标 能够知道受控组件是什么 能够写出受控组件 了解非受控组件 表单处理 受控组件(★★★) HTML中的表单元素是可输入的,也就是有自己的可变状态 而React中可变状态通常保存在s ...

  3. React(一)react概述、组件、事件

    目录 一.React概述 1.脚本方式创建react初始模板 2.react的封装 二.组件 1.函数方式定义组件 2.函数组件传参 3.类方式定义组件 4.类组件传参 三.事件 一.React概述 ...

  4. Java并发编程实战_一线大厂架构师整理:java并发编程实践教程

    并发编程是Java语言的重要特性之一, 在Java平台上提供了许多基本的并发功能来辅助开发多线程应用程序.然而,这些相对底层的并发功能与上层应用程序的并发语义之间并不存在一种简单而直观的映射关系.因此 ...

  5. 收藏 | 700页NLP算法在百度、阿里、腾讯等一线大厂的最佳实践!PDF限时领!

    NLP算法在百度.阿里.腾讯等一线大厂的最佳实践? NLP以及知识图谱在业界的进展? 下阶段我们的发展方向有哪些? 今天,2020 DataFunTalk 精选: <NLP算法在业界的应用实践合 ...

  6. React Native 二 常用组件与开源组件

    2019独角兽企业重金招聘Python工程师标准>>> #0.手把手教React Native实战之开山篇##作者简介东方耀 Android开发RN技术 facebookgithub ...

  7. react 最佳实践_最佳React教程

    react 最佳实践 React is a JavaScript library for building user interfaces. It was voted the most loved i ...

  8. [react] 说出几点你认为的React实践

    [react] 说出几点你认为的React最佳实践 使用HOC实现组件复用 完善测试用例Testing 使用Typescript或者Flow对代码进行静态检测 代码规范及格式化ES lint, Pre ...

  9. react ui框架_Web开发 React 学习(二十)连载基础篇大结局

    系列文章: 测开技能--Web开发 React 学习(一) 测开技能--Web开发 React 学习(二)环境搭建 测开技能--Web开发 React 学习(三)元素的渲染 测开技能--Web开发 R ...

最新文章

  1. js html转图片 ie8,用js滤镜实现在IE8-的图片旋转效果实现不了
  2. H.265在QRTC场景的落地运用
  3. Html5中新增的表单元素详解
  4. Eclipse中部分快捷键
  5. html天猫倒计时代码,怎么用JavaScript编写一个天猫上使用的倒计时?
  6. POJ 1154题解,此题不难理解方法就是DFS,属于水题。不过有一些细节要注意。...
  7. Android开发笔记(三十八)列表类视图
  8. mysql数据库修改排序规则
  9. Debian更新软件源提示There is no public key available for the following key IDs的解决方法
  10. Shell脚本查询进程存活信息
  11. python颜色识别_python实现简单颜色识别程序
  12. STM32与串口屏交互(USART HMI)
  13. #今日论文推荐#CVPR 2022 | 道高一尺,魔高一丈,ConvNet还是ViT?
  14. Office系列---将Office文件(Word、PPT、Excel)转换为PDF文件,提取Office文件(Word、PPT)中的所有图片
  15. 微信网页授权之取消授权
  16. 《Springer》宣布免费对外开放的书籍下载
  17. python获取指定端口流量_python如何查看系统网络流量的信息
  18. android盒子 小米遥控,小米盒子遥控器手机版下载-小米盒子遥控器appv6.0.0 安卓版 - 极光下载站...
  19. 电机专题:控制电机介绍
  20. Goland导入github包

热门文章

  1. RAW Power for Mac(强大的raw图像处理软件)
  2. 是否可以在iOS模拟器中禁用网络?
  3. 22春天津大学《钢筋混凝土结构(1)》在线作业1
  4. 打造Ubuntu媒体中心 —— 10款顶级视频处理软件推荐
  5. 微信小程序:全网独家小程序版本独立微信社群人脉
  6. 2022全新Java300集强势来袭,零基础入学,就像玩游戏一样简单
  7. 交换机telnet配置
  8. Rstudio常用操作
  9. List遍历remove的那些事
  10. HTML5数据加载中请稍后效果,IE8浏览器中一直处于“正在努力地加载数据中,请稍候……”...