当前位置: 首页 > news >正文

面试官:你是怎样进行react组件代码复用的

mixin

Mixin 设计模式

Mixin(混入)是一种通过扩展收集功能的方式,它本质上是将一个对象的属性拷贝到另一个对象上面去,可以拷贝多个属性到一个对象上,为了解决代码复用问题。

常用的方法:JQuery 的 extend 方法。

var LogMixin = {log: function() {console.log('log');},componentDidMount: function() {console.log('in');},componentWillUnmount: function() {console.log('out');}
};var User = React.createClass({mixins: [LogMixin],render: function() {return (<div>...</div>)}
});var Goods = React.createClass({mixins: [LogMixin],render: function() {return (<div>...</div>)}
});

缺点

  1. Mixin 可能会相互依赖,相互耦合,不利于代码维护
  2. 不同的 Mixin 中的方法可能会相互冲突
  3. 现在大量使用 ES6 语法后,React.createClass 已经取消,这种方式也不再推荐

高阶组件(HOC)

高阶组件的定义:

高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。 (高阶组件是参数为组件,返回值为新组件的函数。)

具体的意思就是:
高阶组件可以看作 React 对装饰模式的一种实现,高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件。他会返回一个增强的 React 组件。高阶组件可以让我们的代码更具有复用性,逻辑性与抽象性,可以对 render 方法进行劫持,也可以控制 props 与 state。

const EnhancedComponent = higherOrderComponent(WrappedComponent);

实现高阶组件的两种方式:

  1. 属性代理: 高阶组件通过被包裹的 React 组件来操作 props
  2. 反向继承:高阶组件继承于被包裹的 React 组件。

属性代理

import React,{Component} from 'react';const HOC = (WrappedComponent) =>class WrapperComponent extends Component {state = { number: 0 };btnClick = () => {this.setState({number: this.state.number++})}render() {const newProps = {btnClick: this.btnClick,number: this.state.number}return (<div>rere HOC<WrappedComponent {...this.props} {...this.newProps} /></div>)}
}export default HOC;class MyComponent extends Component{//...
}export default HOC(MyComponent)

这里最重要的部分是render 方法中返回的 WrappedComponent 的 React 组件,这样就可以通过高阶组件来传递 props,这就是属性代理。

这样组件就可以一层层地作为参数被调用,原始组件就具备了高阶组件对它的修饰,也保持了单个组件的封装性,与易用性。参考 前端进阶面试题详细解答

特点

  1. 控制 props
    我们可以在 HOC 里面对 props 进行增删查改等操作

    const MouseHoc = (MouseComponent, props) => {props.text = props.text + "---I can operate props";return class extends React.Component {render() {return (<div style={{ height: "100%" }} onMouseMove={this.handleMouseMove}><MouseComponent {...props} mouse={this.state} /></div>);}};
    };
    MouseHoc(Mouse, {text: "some thing..."
    });
    
  2. 通过 refs 使用引用

    function refHOC(WrappedComponent) {return class extends Component {componentDidMount() {this.wapperRef.log();}render() {return (<WrappedComponent{...this.props}ref={ref => {this.wapperRef = ref;}}/>);}};
    }
    
  3. 抽象 state

  4. 渲染劫持
    高阶组件可以在 render 函数中做非常多的操作,从而控制原组件的渲染输出。只要改变了原组件的渲染,我们都将它称之为一种渲染劫持。

    function visibleHOC(WrappedComponent) {return class extends Component {render() {if (this.props.visible === false) return null;return <WrappedComponent {...props} />;}};
    }
    
  5. 使用其他元素包裹 WrappedCompoennt
    修改 props

反向继承

const MyContainer = (WrappedComponent) =>class extends WrappedComponent{render(){return super.render();}}

这里返回的组件继承了 WrappedComponent,因为被动地继承了 WrappedComponent,所有的调用都会反向。

注意事项

  1. 当我们应用 HOC 去增强另一个组件时,我们实际使用的组件已经不是原组件了,所以我们拿不到原组件的任何静态属性,我们可以在 HOC 的结尾手动拷贝他们

    function proxyHOC(WrappedComponent) {class HOCComponent extends Component {render() {return <WrappedComponent {...this.props} />;}}HOCComponent.staticMethod = WrappedComponent.staticMethod;// ...return HOCComponent;
    }
    
2. 不要在 render 方法内创建高阶组件3. 不要改变原始组件(高阶组件就是一个没有副作用的纯函数。)4. 透传不相关的 props### 解决的问题1. 高阶组件就是一个没有副作用的纯函数,各个高阶组件不会互相依赖耦合
2. 高阶组件也有可能造成冲突,但我们可以在遵守约定的情况下避免这些行为
3. 高阶组件并不关心数据使用的方式和原因,而被包裹的组件也不关心数据来自何处。高阶组件的增加不会为原组件增加负担### 存在的问题1. HOC 需要在原组件上进行包裹或者嵌套,如果大量使用 HOC,将会产生非常多的嵌套,这让调试变得非常困难
2. HOC 可以劫持 props,存在相同名称的 props,则存在覆盖问题在不遵守约定的情况下也可能造成冲突,而且 react 并不会报错。
3. 当存在多个 HOC 时,你不知道 Props 是从哪里来的。
4. HOC 属于静态构建,静态构建即是重新生成一个组件,即返回的新组件,不会马上渲染,即新组件中定义的生命周期函数只有新组件被渲染时才会执行。**在这个范式下,代码通过一个类似于 装饰器(decorator) 的技术进行共享。首先,你的一个组件定义了大量需要被渲染的标记,之后用若干具有你想用共享的行为的组件包裹它。因此,你现在是在 装饰 你的组件,而不是混入你需要的行为!## Render props> Render Props 从名知义,也是一种剥离重复使用的逻辑代码,提升组件复用性的解决方案。在被复用的组件中,**通过一个名为“render”(属性名也可以不是 render,只要值是一个函数即可)的属性,该属性是一个函数,这个函数接受一个对象并返回一个子组件,会将这个函数参数中的对象作为 props 传入给新生成的组件**。### 它的特点1. 传入函数的属性,就是  想要共享的 state,这个相同的 state 是组件的状态,或者行为
2. 术语 “render prop” 是指一种技术,用于使用一个值为函数的 prop 在 React 组件之间的代码共享。
3. render prop 仅仅就是一个函数。
4. `render prop`是一种模式,重点是 prop,而不是 render,任何被用于告知组件需要渲染什么内容的函数 prop 在技术上都可以被称为 “render prop”.
5. 这里的组合模型是 动态的!每次组合都发生在 render 内部,因此,我们就能利用到 React 生命周期以及自然流动的 props 和 state 带来的优势。
6. 具有 render prop 的组件接受一个函数,该函数返回一个 React 元素并调用它,而不是实现自己的渲染逻辑### 小栗子```xml
<DataProvider render={data => (<h1>Hello {data.target}</h1>
)}/>

优势

  1. 不用担心 Props 是从哪里来的, 它只能从父组件传递过来。
  2. 不用担心 props 的命名问题。
  3. render props 是动态构建的。

可以用 render props来代替 HOC

const withMouse = (Component) => {return class extends React.Component {render() {return <Mouse render={mouse => (<Component {...this.props} mouse={mouse}/>)}/>}}
}

Hook

在 Hooks 出现以前,我们总是纠结的问题:

  1. 无状态组件 VS Class 组件

  2. 生命周期
    componentDidMount 和 componentDidUpdate 需要做相同的事情

  3. this 指向
    为了保证 this 的指向正确,我们经常这么写

    this.handleClick = this.handleClick.bind(this)
    <button onClick={() => this.handleClick(e)}>
    
  4. HOC 和 render props 增加我们代码的层级关系

动机

Hook 的作用

  1. 我们的函数变成了一个有状态的函数
  2. Hooks 本质上就是一类特殊的函数,它们可以为你的函数型组件(function component)注入一些特殊的功能(生命周期钩子的功能:useEffect;上下文(context):useContext)
  3. 解决 this 指向问题

State Hooks

Effect Hooks

我们写的有状态组件,通常会产生很多的副作用(side effect)。之前都把这些副作用的函数写在生命周期函数钩子里,比如 componentDidMount,componentDidUpdate 和 componentWillUnmount。而现在的 useEffect 就相当与这些声明周期函数钩子的集合体。它以一抵三。

用 Effect Hooks 来解决这个这些副作用。

注意点

  1. react 首次渲染和之后的每次渲染都会调用一遍传给 useEffect 的函数。而之前我们要用两个声明周期函数来分别表示首次渲染(componentDidMount),和之后的更新导致的重新渲染(componentDidUpdate)。
  2. 函数是异步执行的,而之前的 componentDidMount 或 componentDidUpdate 中的代码则是同步执行的
  3. 怎么解绑副作用
  4. 跳过一些不必要的副作用函数

使用范围

只能在 React 函数式组件或自定义 Hook 中使用 Hook。

Hook 的提出主要就是为了解决 class 组件的一系列问题,所以我们不能在 class 组件中使用它。

相比函数,编写一个 class 可能需要掌握更多的知识,需要注意的点也越多,比如 this 指向、绑定事件等等。另外,计算机理解一个函数比理解一个 class 更快。Hooks 让你可以在 classes 之外使用更多 React 的新特性。

相关文章:

面试官:你是怎样进行react组件代码复用的

mixin Mixin 设计模式 Mixin&#xff08;混入&#xff09;是一种通过扩展收集功能的方式&#xff0c;它本质上是将一个对象的属性拷贝到另一个对象上面去&#xff0c;可以拷贝多个属性到一个对象上&#xff0c;为了解决代码复用问题。 常用的方法&#xff1a;JQuery 的 exte…...

arxiv2017 | 用于分子神经网络建模的数据增强 SMILES Enumeration

论文标题&#xff1a;SMILES Enumeration as Data Augmentation for Neural Network Modeling of Molecules论文地址&#xff1a;https://arxiv.org/abs/1703.07076代码地址&#xff1a;https://github.com/Ebjerrum/SMILES-enumeration一、摘要摘要中明显提出&#xff1a;先指…...

倒计时2天!TO B人的传统节日,2023年22客户节(22DAY)

去年&#xff0c;2022.02.22&#xff0c;正月二十二星期二&#xff0c;在这个最多2的一天&#xff0c;成功举办了“首届22客户节&#xff08;22DAY&#xff09;”&#xff0c;一群To B互联网人相约杭州见证&#xff1b; 癸卯兔年&#xff0c;2023.02.22&#xff0c;让我们再度…...

java版工程管理系统Spring Cloud+Spring Boot+Mybatis实现工程管理系统源码

java版工程管理系统Spring CloudSpring BootMybatis实现工程管理系统 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和…...

数据结构刷题(六):142环形链表II、242有效的字母异位词、383赎金信、349两个数组的交集

1.环形链表II题目链接思路&#xff1a;设置快慢双指针注意&#xff1a;&#xff08;1&#xff09;是否有环&#xff08;快慢双指针是否能碰面也就是相等&#xff09;&#xff08;2&#xff09;环形入口的判断。从头结点出发一个指针&#xff0c;从相遇节点 也出发一个指针&…...

OpenGL学习日记之光照计算

引言 现实生活中的光照极其复杂&#xff0c;而且会收到很多因素的影响&#xff0c;是我们当前计算机的算力无法模拟的。因此我们会根据一些简化的模型来模拟现实光照&#xff0c;这样在可以模拟出近似的光照感受&#xff0c;但是又没有那么复杂的计算。 常用的光照模型有&…...

七大排序经典排序算法

吾日三省吾身&#xff1a;高否&#xff1f;富否&#xff1f;帅否&#xff1f;答曰&#xff1a;否。滚去学习!!!(看完这篇文章先)目前只有C和C的功底&#xff0c;暂时还未开启新语言的学习&#xff0c;但是大同小异&#xff0c;语法都差不多。目录&#xff1a;一.排序定义二.排序…...

设计模式—“对象性能”

面向对象很好地解决了“抽象”的问题,但是必不可免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理。 典型模式有:Singleton、Flyweight 一、Flyweight 运用共享技术将大量细粒度的对象进项复用,…...

基于Spring Boot的零食商店

文章目录项目介绍主要功能截图&#xff1a;登录后台首页个人信息管理用户管理前台首页购物车部分代码展示设计总结项目获取方式&#x1f345; 作者主页&#xff1a;Java韩立 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关…...

Python语言的优缺点

为初学者而著&#xff01;适合准备入行开发的零基础员学习python。python也是爬虫、大数据、人工智能等知识的基础。感兴趣的小伙伴可以评论区留言&#xff0c;领取视频教程资料和小编一起学习&#xff0c;共同进步&#xff01;https://www.bilibili.com/video/BV13D4y1G7pt/?…...

3款强大到离谱的电脑软件,个个提效神器,从此远离加班

推荐3款让你偷懒&#xff0c;让你上头的提效电脑软件&#xff0c;个个功能强大&#xff0c;让你远离加班&#xff01; 很多几个小时才能做好的事情&#xff0c;用上它们&#xff0c;只需要5分钟就行&#xff01;&#xff01; 1、JNPF —— 个人最喜欢的低代码软件 它为开发者…...

vue3 使用typescript小结

最近学习vue3 typescript&#xff0c;网上看了很多文章&#xff0c;汇总一下&#xff0c;分享给大家&#xff0c;希望会对大家有帮助。 一. 为props标注类型 defineProps()宏函数支持从它的参数中推导类型&#xff1a; <script setup langts>import { defineProps } fro…...

PYTHON爬虫基础

一、安装package 在使用爬虫前&#xff0c;需要先安装三个包&#xff0c;requests、BeautifulSoup、selenium。 输入如下代码&#xff0c;若无报错&#xff0c;则说明安装成功。 import requests from bs4 import BeautifulSoup import selenium二、Requests应用 了解了原理…...

JavaScript刷LeetCode模板技巧篇(一)

虽然很多人都觉得前端算法弱&#xff0c;但其实 JavaScript 也可以刷题啊&#xff01;最近两个月断断续续刷完了 leetcode 前 200 的 middle hard &#xff0c;总结了一些刷题常用的模板代码。 常用函数 包括打印函数和一些数学函数。 const _max Math.max.bind(Math); co…...

ros-sensor_msgs/PointCloud2消息内容解释

1.字段解释 header-----头文件&#xff0c;包含消息的序列号&#xff0c;时间戳(系统时间)和坐标系id&#xff0c;其中secs为秒&#xff0c;nsecs为去除秒数后剩余的纳秒数 height-----点云的高度&#xff0c;如果是无序点云&#xff0c;则为1&#xff0c;例子中的点云为有序点…...

LeetCode 每日一题2347. 最好的扑克手牌

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…...

MMPBSA计算--基于李继存老师gmx_mmpbsa脚本

MMPBSA计算–基于李继存老师gmx_mmpbsa脚本 前期准备 软件安装 安装gromacs, 可以查阅 我的blogGromacs-2022 GPU-CUDA加速版 unbantu 安装 apbs, sudo apt install apbs 安装 gawk, sudo apt install gawk MD模拟好的文件 我们以研究蛋白小分子动态相互作用-III(蛋白配体…...

Kafka优化篇-压测和性能调优

简介 Kafka的配置详尽、复杂&#xff0c;想要进行全面的性能调优需要掌握大量信息&#xff0c;这里只记录一下我在日常工作使用中走过的坑和经验来对kafka集群进行优化常用的几点。 Kafka性能调优和参数调优 性能调优 JVM的优化 java相关系统自然离不开JVM的优化。首先想到…...

MinIo-SDK

3.2.5 SDK 3.2.5.1上传文件 MinIO提供多个语言版本SDK的支持&#xff0c;下边找到java版本的文档&#xff1a; 地址&#xff1a;https://docs.min.io/docs/java-client-quickstart-guide.html 最低需求Java 1.8或更高版本: maven依赖如下&#xff1a; XML<dependency&g…...

系统分析师真题2018试卷相关概念一

面向对象的基本概念: 对象的三要素为:属性(数据)、方法(操作)、对象ID(标识)UML2.0包括14种图: 类图(class diagram):类图描述一组类、接口、协作和他们之间的关系。在OO系统的建模中,最常见的图就是类图。类图给出了系统的静态设计图,活动类的类图给出了系统的静…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...