根据Vue对比来深入学习React 下 props 组件传值 插槽 样式操作 hooks 高阶组件 性能优化
文章目录
- 函数组件的特点
- props
- 组件间的传值
- 父传子看上例
- 子传父
- 兄弟组件传值
- 祖先组件传值
- 插槽
- 基础插槽
- 具名插槽
- 作用域插槽
- 样式操作
- **CSS Modules**
- 生命周期
- useRef
- 常用hook
- useState
- useEffect
- useContext
- useReducer
- useMemo
- useCallback
- 高阶组件
- 什么时候使用
- react性能问题和优化
- React的时间切片
- fiber
- 避免父组件数据导致子组件更新
函数组件的特点
- 函数组件没有生命周期
- 函数组件没有this
- 函数组件通过hook来完成各种操作
- 函数组件本身的函数体相当于render函数
- props在函数的第一个参数接受
props
props是react中的核心
在react中,一切写在组件上的属性和子节点都被规划为了props。
所以props是react很多功能的根本。父子传值,插槽全都是基于props,不像Vue有事件监听,emit,专门的插槽这一类东西
//也可以给默认值
function Avatar({ person, size= 100 }) {return (<imgclassName="avatar"src={getImageUrl(person)}alt={person.name}width={size}height={size}/>);
}export default function Profile() {return (<div><Avatarsize={100}person={{ name: 'Katsuko Saruhashi', imageId: 'YfeOqp2'}}/></div>);
}
组件间的传值
父传子看上例
子传父
子组件可以通过回调函数将数据传递回父组件。没有Vue中的emit和expose方法
// 子组件const ChildComponent = ({ onSendData }) => {return <button onClick={() => onSendData("Hello from Child!")}>Send Data</button>;};// 父组件const ParentComponent = () => {const handleData = (data) => {console.log(data);};return <ChildComponent onSendData={handleData} />;};
兄弟组件传值
与Vue相同 都是通过父组件作为中介来传递数据。
// 第一个兄弟组件const BrotherOne = ({ onSendData }) => {return <button onClick={() => onSendData("Data from Brother One")}>Send Data</button>;};// 第二个兄弟组件const BrotherTwo = ({ data }) => {return <h1>{data}</h1>;};// 父组件const ParentComponent = () => {const [data, setData] = React.useState("");const handleDataChange = (newData) => {setData(newData);};return (<div><BrotherOne onSendData={handleDataChange} /><BrotherTwo data={data} /></div>);};
祖先组件传值
import React, { createContext, useContext, useState } from 'react';JJ// 创建 Contextconst MyContext = createContext();// 提供者组件const MyProvider = ({ children }) => {const [value, setValue] = useState("Hello from Context!");return (<MyContext.Provider value={{ value, setValue }}>J{children}</MyContext.Provider>);};// 使用 Context 的子组件const ChildComponent = () => {const { value } = useContext(MyContext);return <h1>{value}</h1>;};// 父组件const ParentComponent = () => {return (<MyProvider><ChildComponent /></MyProvider>);};
插槽
在 React 中,虽然没有 Vue 的插槽(slot)具名插槽 作用域插槽,但是可以实现
插槽本质上讲就是子组件的html内容需要父组件传入,在jsx的加持下,我可以把html像普通的字符串,数字一样传递,所以插槽只需要直接作为props传入就行
基础插槽
在基础插槽中,我们可以使用 children
prop 来接收父组件传递的内容
import React from 'react';// 容器组件,支持基础插槽const Container = ({ children }) => {return (<div className="container"><h2>Container Header</h2><div className="content">{children}</div></div>);};// 使用容器组件const App = () => {return (<Container><p>This is the content inside the container.</p></Container>);};
export default App;
具名插槽
可以通过将不同的 props 传递给子组件来实现。我们可以使用标准的 JSX 语法来实现具名插槽
import React from 'react';
// 容器组件,支持具名插槽const Container = ({ header, footer, children }) => {return (<div className="container"><div className="header">{header}</div><div className="content">{children}</div><div className="footer">{footer}</div></div>);};// 使用容器组件const App = () => {return (<Containerheader={<h1>This is the Header</h1>}footer={<h2>This is the Footer</h2>}><p>This is the main content area.</p></Container>
);
};
export default App;
作用域插槽
允许我们将数据传递到子组件,使得父组件可以控制子组件的渲染。我们可以通过传递一个函数作为 prop 来实现
import React from 'react';
// 容器组件,支持作用域插槽const ListContainer = ({ items, renderItem }) => {return (<ul>{items.map(item => (<li key={item.id}>{renderItem(item)}</li>))}</ul>);};
// 使用容器组件const App = () => {const items = [{ id: 1, text: 'Item 1' },{ id: 2, text: 'Item 2' },{ id: 3, text: 'Item 3' }];const renderItem = (item) => <span>{item.text}</span>;return (<ListContainer items={items} renderItem={renderItem} />);};export default App;
样式操作
class类名设值:必须写为className 类名和样式写在css文件里 必须接受一个字符串
style内联:不能像原生一样写成字符串,必须写成对象
import React from 'react';import './styles.css'; // 这里引入你的 CSS 文件const MyComponent = ({ className, style }) => {return (<div className={className} style={style}>Hello, World!</div>);};// 使用组件const App = () => {const customStyle = {color: 'blue',fontSize: '20px',backgroundColor: 'lightgray',};return (<MyComponentclassName="my-custom-class" // 在 CSS 文件中定义的类名style={customStyle} // 使用对象形式的内联样式/>);};export default App;
CSS Modules
CSS Modules 提供了局部作用域的 CSS,避免类名冲突。
//styles.module.css
.myCustomClass { color: blue; font-size: 20px; padding: 10px; background-color: lightgray; }import styles from './styles.module.css';
const MyComponent = () => { return <div className={
styles.myCustomClass}>
Hello, World!
</div>;};
生命周期
在 React 函数组件中,没有传统的生命周期方法 ,React 通过 Hooks 提供了类似的功能,允许你在不同的阶段执行副作用。
import React, { useEffect } from 'react';const MyComponent = () => {useEffect(() => {// 组件挂载时执行return () => {// 组件卸载时执行};}, []); // 空数组表示只在挂载和卸载时执行return <div>Hello, World!</div>;};
useRef
用于获取真实dom和vue中ref一个道理 只不过变成了.current
import React, { useRef } from 'react';const MyComponent = () => {const inputRef = useRef(null);const focusInput = () => {if (inputRef.current) {inputRef.current.focus();}};return (<div><input ref={inputRef} type="text" /><button onClick={focusInput}>Focus Input</button></div>);};
常用hook
useState
语法: const [state, setState] = useState(initialState)
initialState
是初始状态,可以是任何类型(数字、字符串、对象等)。setState
是更新状态的函数。
这个不做举例了
useEffect
语法:useEffect(() => { … },[dependencies])
dependencies
是一个数组,包含 effect 依赖的值。当这些值发生变化时,effect 会重新执行。如果传入空数组 []
,effect 只会在组件挂载和卸载时执行一次。
不做举例了
useContext
语法:const value = useContext(MyContext)
useContext
不接受第二个参数。它从最近的 <MyContext.Provider>
中获取当前上下文值
useReducer
用法: const [state, dispatch] = useReducer(reducer, initialState);
第二个参数: initialState
是 reducer 的初始状态,通常是一个对象或基本数据类型。
import React, { useReducer } from 'react';const initialState = { count: 0 };function reducer(state, action) {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };default:throw new Error();}}const Counter = () => {const [state, dispatch] = useReducer(reducer, initialState);return (<div>Count: {state.count}<button onClick={() => dispatch({ type: 'increment' })}>+</button><button onClick={() => dispatch({ type: 'decrement' })}>-</button></div>);};
useMemo
用法:const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
dependencies
是一个数组,当数组中的任意一个值改变时,computeExpensiveValue
才会重新计算并返回新值
可以提高性能 记忆函数 也就是保存结果,组件多次渲染直接取缓存结果就行
import React, { useMemo } from 'react';const ExpensiveCalculation = ({ num }) => {const result = useMemo(() => {// 进行复杂计算return num * 2; // 示例计算}, [num]); // 依赖于 numreturn <div>Result: {result}</div>;};
useCallback
用法: const memoizedCallback = useCallback(() => { }, [dependencies]);
第二个参数: dependencies
是一个数组,当数组中的任意一个值改变时,返回新的回调函数。
更上面一样 就是保存函数
import React, { useState, useCallback } from 'react';const Button = React.memo(({ onClick }) => {console.log('Button Rendered');return <button onClick={onClick}>Click Me</button>;});const App = () => {const [count, setCount] = useState(0);const handleClick = useCallback(() => {setCount(count + 1);}, [count]); // 依赖于 countreturn (<div><Button onClick={handleClick} /><p>Count: {count}</p></div>);};
高阶组件
高阶组件(Higher-Order Component,简称 HOC)是 React 中一种用于复用组件逻辑的模式。它本质上是一个函数,接受一个组件作为参数,并返回一个新的组件。高阶组件可以用于许多场景,例如:状态管理、数据获取、权限控制等。
import React from 'react';// 原始组件const MyComponent = ({ extraInfo }) => (<div><p>这是我的组件。</p><p>{extraInfo}</p></div>);// 高阶组件const withExtraInfo = (WrappedComponent) => {return (props) => {const extraInfo = "附加信息:这是来自高阶组件的内容!";return <WrappedComponent {...props} extraInfo={extraInfo} />;};};// 使用高阶组件const EnhancedComponent = withExtraInfo(MyComponent);const App = () => (<div><EnhancedComponent /></div>);export default App;
什么时候使用
组件是既包含了ui界面的复用,也包含了逻辑的复用,高阶组件只是复用操作逻辑,运算,类似于vue中mixin的用途,当我们发现某个操作逻辑,或者某个运算经常出现的时候,我们可以提取为高阶组件
react性能问题和优化
Vue的因为是在get和set里触发更新
Vue在get部分有一个重要的操作-依赖收集
这样我们在更改了数据后,只会更新用到了这个数据的地方做到最小的更新范围
React的更新是调用方法时触发的,并没有依赖收集的过程所以他会更新整个组件树也就是会把子组件一起更新即使更新的数据和子组件没有任何关系
所以React最大的一个性能问题就是-React的某个组件的更新会连带着,他的子组件一起更新。所以我们需要解决这个问题让子组件只做合理的更新
React的时间切片
Vue有依赖收集,做到了最小的更新范围,而React没有做这个事情。所以React要更新,就会有很大的diff算法比对和计算工作
这大的更新量,虚拟dom比对和计算会花很大时间,这样可能会阻塞住浏览器的工作,导致页面长时间白屏
React为了解决这个问题选择另一种策略-时间切片,也就是先计算一部分更新,然后让渡给渲染进程 然后再进行下一步更新我从使用者的角度 就不会出现长时间白屏了。
fiber
为了支持这种切片,我们需要把更新化成一个个单元,然后我们也必须有回复上一次计算进度的能力
所以react设计一种数据结构-fiber
每一个组件会被转化为一个fiber结构的对象,组成一个个单元。Fiber让我们有了回复上次中断的计算进度的能力
类似于vue中的虚拟节点vnode, Both Fiber 和 vnode 都是对真实 DOM 的抽象,旨在提高性能和效率。它们允许框架在内存中处理组件树,而不是直接操作 DOM。
避免父组件数据导致子组件更新
React.memo
子组件 让它缓存
我们特别注意父组件传入的方法,对象,数组这样的引用类型
用useCallback包裹传递给子组件的方法
state对象,数组数据,要用useMemo包裹起来
import React, { useState, useCallback, useMemo } from 'react';// 子组件const ChildComponent = React.memo(({ handleClick, data }) => {console.log('ChildComponent rendered');return (<div><button onClick={handleClick}>Click Me</button><ul>{data.map((item, index) => (<li key={index}>{item}</li>))}</ul></div>);});// 父组件const ParentComponent = () => {const [count, setCount] = useState(0);const [items, setItems] = useState(['Item 1', 'Item 2']);// 使用 useCallback 包裹传递给子组件的方法const handleClick = useCallback(() => {setCount(count + 1);}, [count]);// 使用 useMemo 包裹传递给子组件的数组数据const memoizedItems = useMemo(() => {return items;}, [items]);return (<div><h1>Count: {count}</h1><ChildComponent handleClick={handleClick} data={memoizedItems} /></div>);};export default ParentComponent;
如果对你有所帮助的话就点个关注吧,会持续更新技术文章
相关文章:

根据Vue对比来深入学习React 下 props 组件传值 插槽 样式操作 hooks 高阶组件 性能优化
文章目录 函数组件的特点props组件间的传值父传子看上例子传父兄弟组件传值祖先组件传值 插槽基础插槽具名插槽作用域插槽 样式操作**CSS Modules** 生命周期useRef常用hookuseStateuseEffectuseContextuseReduceruseMemouseCallback 高阶组件什么时候使用 react性能问题和优化…...
HTML(六)超链接
HTML讲解(一)body部分_html body-CSDN博客 <!DOCTYPE html> <html><head><meta charset"UTF-8" /><title>title</title> </head><body><a href"https://blog.csdn.net/2301_8034953…...
【Coroutines】Implement Lua Coroutine by Kotlin - 2
Last Chapter Link 文章目录 Symmetric CoroutinesNon-Symmetric Coroutine SampleSymmetric Coroutine SampleHow to Implement Symmetric CoroutinesWonderful TricksCode DesignTail Recursion OptimizationFull Sources Symmetric Coroutines in last blog, we have talk…...

java计算机毕设课设—扫雷游戏(附源码、文章、相关截图、部署视频)
这是什么系统? 资源获取方式再最下方(本次10月份活动福利,免费提供下载,自行到对应的方式1下载,csdn的0积分下载) java计算机毕设课设—扫雷游戏(附源码、文章、相关截图、部署视频) 基于Java的扫雷游戏…...

AndroidLogger 使用问题
Q1:解压zip后,启动Notepad未看到AndroidLogger工具栏 请检查plugins下安装位置是否正确,必须与下图一致,再确认Notepad 是否为 x64 ? Q2:使用 adb 可以显示已连接,但是获取不到日志 暂时不确定问…...

数据库常见面试
8道面试题 目录 目录 7道面试题 1.怎样进行sql优化 4、group by优化 5、limit优化 6、count优化 7、update优化 2.。怎样查看sql执行情况呢(哪个关键字),说说你对这个关键字的认识 4) possible_key: 5) key 3.说说你对innodb和 myisam的理解 …...

boxplot 绘制箱线图,添加数据点
先看效果图 import matplotlib.pyplot as plt #! 解决不显示的问题:中文设置为宋体格式 plt.rcParams[font.family] ["Times New Roman", SimSun]def plot_boxplot(data_list, out_file, x_custom_labels):# 画图fig, ax plt.subplots(figsize(90, 6…...

用sdkman管理多个jdk切换
前言 最近项目前后端进行升级,需要在jdk8和jdk17两个版本切换。最简单的是通过手动切换,但切换过程太繁琐,修改环境变量,达到切换目的。于是尝试其它解决方案,最终确实使用sdkman工具。 sdkman 是一款面向Java开发者的…...

【AIGC】ChatGPT提示词Prompt高效编写模式:结构化Prompt、提示词生成器与单样本/少样本提示
💯前言 在如今AI技术迅猛发展的背景下,尽管像ChatGPT这样的大型语言模型具备强大的生成能力,但它们的输出质量有时仍难以完全满足我们的预期。为了让ChatGPT生成更加准确、可靠的内容,掌握高效的Prompt编写技巧变得尤为重要。本文…...

反调式实战(有道翻译窗口弹出)
1.添加脚本断点实现源码获取 2.Function构造器构造debugger 因为是窗口被弹出的情况,所以window.closefunction()构造debugger。 3.定位到影响弹出的JavaScript代码片段 反调试思想:置空和替换,所以将其JavaScript进行注释或者删除。 这里主…...

verilog端口使用注意事项
下图存在组合逻辑反馈环,即组合逻辑的输出反馈到输入(赋值的左右2边存在相同的信号),此种情况会造成系统不稳定。比如在data_in20的情况下,在data_out0 时候,输出的数据会反馈到输入,输入再输出,从而造成不…...
Docker常用命令大全汇总
Docker是一种流行的容器化平台,可以在一个独立的、隔离的环境中构建、部署和运行应用程序。了解Docker常用命令可以帮助我们更高效地管理容器,快速开发和部署应用。本文将整理一系列Docker的常用命令,便于日常使用和学习。 1 Docker基础命令 1.1 启动/停止/重启docker # …...

LVS-DR+Keepalived 高可用群集部署
LVS-DRKeepalived 高可用群集部署 Keepalived 的工作原理LVSKeepalived 高可用群集部署配置负载调度器(主、备相同)关闭防火墙和核心防护及准备IPVS模块配置keeplived(主、备DR 服务器上都要设置)启动 ipvsadm 服务调整 proc 响应…...
【elasticsearch】安装和启动
启动 Elasticsearch 并验证其是否成功运行通常涉及以下步骤: 下载和安装 Elasticsearch: 访问 Elasticsearch 官方网站下载页面:https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html根据你的操作系…...
Golang 逃逸分析(Escape Analysis)理解与实践篇
Golang 逃逸分析(Escape Analysis)理解与实践篇 文章目录 1.逃逸分析2.相关知识(栈、堆、GC分析)3.逃逸分析综合-实践 demo 逃逸分析(Escape Analysis)是编译器在编译期进行的一项优化技术,是Gl…...

React入门 9:React Router
1. 什么是路由 路由(routing)就是通过互联的网络把信息从源地址传输到目的地址的活动。 以上是中文维基百科对路由的解释。通俗的来讲,把一个地方的信息传输到他想去的目的地的过程,就叫路由。 2. 用代码解释路由 需求:…...
MATLAB基础应用精讲-【数模应用】Bland-Altman图(附python和R语言代码实现)
目录 前言 几个高频面试题目 Bland-altman图:如何改变y轴 算法原理 Bland-Altman一致性分析 一致性界限 1. 背景介绍 2. Bland-Altman 法 3. batplot 命令介绍 4. 应用实例 Prism GraphPad实现Bland-Altman图 1.输入数据 2.从数据表中选择Bland-Altman分析 3.检…...
ARM/Linux嵌入式面经(四一):中兴面经
1. 请介绍一下您在嵌入式系统开发中的项目经验。 在嵌入式系统开发领域,我积累了丰富的项目经验,这些经验不仅锻炼了我的技术能力,也让我对嵌入式系统的设计和实现有了更深入的理解。以下是我参与的一个具有代表性的嵌入式系统开发项目的详细介绍: 项目背景 该项目是为一…...

鸿蒙虚拟运行环境
加一个环境变量:%SystemRoot%\System32\Wbem pushd "%~dp0" dir /b %SystemRoot%\servicing\Packages\*Hyper-V*.mum >hyper-v.txt for /f %%i in (findstr /i . hyper-v.txt 2^>nul) do dism /online /norestart /add-package:"%SystemRoot%…...

SpringCloud-Consul
为什么引入 Consul 简介以及安装 控制台 localhost:8500 服务注册与发现 服务端 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-consul-discovery</artifactId><exclusions><exclusio…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...

DAY 45 超大力王爱学Python
来自超大力王的友情提示:在用tensordoard的时候一定一定要用绝对位置,例如:tensorboard --logdir"D:\代码\archive (1)\runs\cifar10_mlp_experiment_2" 不然读取不了数据 知识点回顾: tensorboard的发展历史和原理tens…...

goreplay
1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具,可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长,测试它所需的工作量也会呈指数级增长。GoRepl…...
IP选择注意事项
IP选择注意事项 MTP、FTP、EFUSE、EMEMORY选择时,需要考虑以下参数,然后确定后选择IP。 容量工作电压范围温度范围擦除、烧写速度/耗时读取所有bit的时间待机功耗擦写、烧写功耗面积所需要的mask layer...
leetcode 386. 字典序排数 中等
给你一个整数 n ,按字典序返回范围 [1, n] 内所有整数。 你必须设计一个时间复杂度为 O(n) 且使用 O(1) 额外空间的算法。 示例 1: 输入:n 13 输出:[1,10,11,12,13,2,3,4,5,6,7,8,9]示例 2: 输入:n 2…...
全面解析网络端口:概念、分类与安全应用
在计算机网络的世界里,数据的传输与交互如同一场繁忙的物流运输,而网络端口就是其中不可或缺的 “货运码头”。无论是日常浏览网页、收发邮件,还是运行各类网络服务,都离不开网络端口的参与。本文将深入介绍网络端口的相关知识&am…...
后端解决跨域问题的三种方案:注解配置 vs 全局配置 vs 过滤器配置(附完整代码详解)
文章目录 一、引言:跨域问题的本质与解决方案分类解决方案分类二、方案一:`WebMvcConfigurer` 全局配置(推荐)1. 核心代码(你提供的 `CorsConfig` 示例)2. 代码详解3. 优点4. 注意事项三、方案二:`CorsFilter` 过滤器配置(传统方式)1. 核心代码(你提供的 `ResourcesC…...