react中关于类式组件和函数组件对props、state、ref的使用

news2024/11/30 0:42:06

文章中有很多蓝色字体为扩展链接,可以补充查看。

常用命令使用规则

组件编写方式:

1.函数式

function MyButton() {
//直接return 标签体
  return (
   <>……</>
  );
}

2.类

class MyButton extends React.Component {
//在render方法中,return 标签体
  render() {
    return <>……</>
  }
}

虚拟dom到底是怎么个事?

-虚拟dom:它本质上是一个拥有着对应着真实的DOM元素的属性集合的 JavaScript对象。
为什么要使用虚拟dom?

答案:我们通过对dom的操作实现浏览器更新,当应用的项目比较小的时候这么做是没有问题的,但是当变更频繁或者需要操作的dom数量大的时候就非常不合适了。因为dom的变更会引起浏览器的重排和重绘,这是十分消耗性能的。
因此引入虚拟dom的概念来改善这种问题,在渲染dom之前,存储一份虚拟dom。每次去变更dom,都会使用最新的虚拟dom去对比之前的,只更新增加不同的部分,避免全量更改真实dom减少开销,以下是使用虚拟dom的好处。

  1. 性能优化: 虚拟DOM使得React可以将多次DOM操作合并为一次,从而减少了实际的DOM操作次数,提高了性能。
  2. 快速更新: React通过比较虚拟DOM和实际DOM的差异,只更新必要的部分,避免了不必要的重新渲染,提高了页面的响应速度。
  3. 框架内部使用: 虚拟DOM是React框架内部使用的一种机制,开发者通常无需直接操作虚拟DOM,React会在合适的时机将其转化为真实的DOM。
vue与react的diff算法的区别

React 和 Vue 都采用了高效的虚拟 DOM Diff 算法来优化视图更新,尽管它们在具体实现上有所不同,但核心目标都是尽可能地减少对真实 DOM 的操作以提升性能。以下是 React 和 Vue diff 算法的主要对比点:

  1. Diff 策略

    • React:React 使用了深度优先搜索(DFS)进行树形结构的比较,并且在同层节点中,默认采用“逐个”比较的方式,只有在找到 key 相同的节点时才进行移动操作,而不是重新创建。当遇到列表类型的子节点时,若没有提供稳定的 key,则会默认复用首尾的节点,中间的节点会被全部卸载并重新创建。
    • Vue:Vue 也是基于 DFS 进行树形结构比较,但它采用的是“双向”遍历的方式,在确定待插入、移动或删除的元素时效率更高。Vue 也强调使用 key 来提高列表渲染性能,如果提供了 key,Vue 可以更精确地识别出被移动或复用的元素。
  2. 异同处理

    • React:React 在同一层级的节点比较中,只要类型不同就会直接替换整个子树,这可能导致不必要的DOM操作。
    • Vue:Vue 对于组件的修改更为灵活,它会尝试复用现有组件实例,即使其类型发生了变化。但如果数据或者 prop 有显著差异,也会触发重建。
  3. 调度策略

    • React:React 16 引入了 Fiber 架构,实现了可中断和恢复的 Diff 算法,允许浏览器在渲染过程中进行其他任务,提高了 UI 响应速度。
    • Vue:Vue 的异步更新队列机制,使得多个数据更改在一起时可以统一进行一次视图更新,一定程度上减少了计算量。
  4. 优化手段

    • React:通过 shouldComponentUpdate 或者 PureComponent、React.memo 提供组件级别的优化。
    • Vue:Vue 则是默认跟踪依赖,通过对象属性代理和响应式系统自动检测变更,配合 computed 属性和 watch 选项进行优化。

总结来说,React 和 Vue 在 Diff 算法上的差异主要体现在具体的遍历策略、组件更新逻辑以及优化方式上,两者都在努力减少不必要的 DOM 操作,提升页面渲染性能。实际开发中,合理使用 key、遵循最佳实践都可以进一步提升二者在大规模数据更新场景下的表现。

使用 JSX 书写标签语言_规则

  1. 标签闭合
  2. 只能返回一个根元素
  3. 使用驼峰式命名法给所有 大部分属性命名!
css
//常用举例 css
<img className="avatar" />

//{}中写入变量
<img
  className="avatar"
  style={{
    width: user.imageSize,
    height: user.imageSize
  }}
/>

//如果你有多个条件类
<img className={cn('row', {
      selected: isSelected,
      large: size === 'large',
      isActived && 'isActived '
    })} />

props、state、ref

props

简单来说props就是组件对外的接口,用于接收父级组件的传递过来的参数的一个口子。通过这个口子可以使子组件使用父组件传递过来的内容。

绝不能修改自身的 props。

- 函数式组件 -
function Button({ onSmash, children }) {
  return (
    <button onClick={onSmash}>
      {children}
    </button>
  );
}

export default function App() {
  return (
    <div>
      <Button onSmash={() => alert('正在播放!')}>
        播放电影
      </Button>
    </div>
  );
}
//总结:在标签中传递,方法参数接收
- 类式组件
import React ,{Component} from 'react'
class App extends Component {
    constructor(props){
      super(props)
    }
    render(){
     return (
    <div>
      <Button onSmash={() => alert('正在播放!')}>
        播放电影
      </Button>
    </div>
  );
  }
}
//总结:在标签中传递,在cunstrctor中接收

在React的类式组件中,即使不写constructor构造函数,也依然可以使用props。React会自动为类组件实例初始化props,无需在构造函数中手动传递。你可以直接在组件类的其他生命周期方法或者成员函数中通过this.props访问到传入的props。

import React ,{Component} from 'react'
class MyComponent extends Component{
   render(){
      const {name ,age } = this.props;
      return (<div>我叫{name},我已经{age}岁了!</div>)
   }
}
//使用组件时使用标签传递props
<MyComponent name='喵喵' age={3} />

state

它是React组件内的一个对象,用于存储组件的动态数据或状态。每个React组件都有自身的state,并且它可以随时间发生变化,进而驱动组件重新渲染,以反映新的状态所导致的UI变化。

  • state如同一张快照,这个观点很重要,请跳转查看。
  • 当你想要批量的操作state值的时候可以使用箭头函数处理。
  • 如果一个值可以基于现有的 props 或 state 计算得出,不要把它作为一个 state,而是在渲染期间直接计算这个值。
function Form() {
  const [firstName, setFirstName] = useState('Taylor');
  const [lastName, setLastName] = useState('Swift');
  // ✅ 非常好:在渲染期间进行计算
  const fullName = firstName + ' ' + lastName;
  // ...
}
  • 更新state的对象是全覆盖模式,而不是替换模式。
  • 操作数组
    在这里插入图片描述
- 函数式组件 -
//1.导入useState hook
import { useState } from 'react';

export default function Gallery() {
  //2.声明state变量 name
  const [name, setName] = useState('喵喵');
  function handleChangeName() {
  //3.改变state变量
    setName('朵喵喵');
  }
  return (
    <>
      <button onClick={handleChangeName}>换个名字</button>
      {name}
    </>
  );
}
- 类式组件 -
import React, { Component } from 'react';

class YourComponent extends Component {
 //1.在constructor中声明
 //constructor(props) {
 //  super(props);
 //  this.state = {
 //    name: "喵喵"
 //  };
 //}
  
  //2.直接声明
  state = {
     name: "喵喵"
  };
 
  handleButtonClick = () => {
     this.setState({
        name: '朵喵喵',
     });
  }

  render() {
   return ( <button onClick={this.handleButtonClick}>{this.state.name}</button> );
  }
}

export default YourComponent;

ref

当你希望组件“记住”某些信息,但又不想让这些信息 触发新的渲染 时,你可以使用 ref 。state的改变会导致页面重新被渲染,而使用ref定义的变量是不会被渲染的。就相当于重新开辟了一个空间用于存储不需要被渲染到页面上的数据,减少一些不必要的渲染开支。

如何使用?
//引入 hook
import { useRef } form 'react'

// 定义,useRef返回一个对象,相当于 const name = useRef('喵喵'){ return { current:‘喵喵’ } }
// 到组件挂载后,this.myDivRef.current才指向真实DOM节点
const name = useRef('喵喵')       //  = { current :'喵喵'}

//使用
export default function Cat(){
   return (<div onClick="() => name.current = '朵喵喵'">改名</div>)
}
ref与state的区别

==更加建议使用state ==
在这里插入图片描述

扩展应用,操作dom

由于 React 会自动处理更新 DOM 以匹配你的渲染输出,因此你在组件中通常不需要操作 DOM。但是,有时你可能需要访问由 React管理的 DOM 元素。

直接操作DOM并不是通常推荐的做法

函数式
//1.
import React, { useRef, useEffect } from 'react';

function MyComponent() {
  //2.
  const divRef = useRef(null);
  function handleChange (){
    //4.修改
    divRef.current.style.backgroundColor = 'red'
  }
  return (
    //3.使用定义的变量
    <div ref={divRef} onClick={handleChange}>
      这个div的背景将会被设置为红色
    </div>
  );
}

export default MyComponent;
类式

在 React 中,JSX 的渲染必须是纯粹操作,不应该包含任何像修改 DOM 的副作用。

import React, { Component, createRef } from 'react';

class MyComponent extends Component {
  myDivRef = createRef();
  
  componentDidMount() {
    // 到组件挂载后,this.myDivRef.current才指向真实DOM节点
    if (this.myDivRef.current) {
      this.myDivRef.current.style.backgroundColor = 'red';
    }
  }

  render() {
    return (
      <div ref={this.myDivRef}>
        这个div的背景将会被设置为红色
      </div>
    );
  }
}

export default MyClassComponent;

关于生命周期

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1603040.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

matlab关于COE文件之读取操作

平台&#xff1a;matlab2021b 场景&#xff1a;在使用fir滤波器后&#xff0c;我们使用matlab生成coe文件后。在xilinx新建IP的后&#xff0c;数据流经过FIR的IP核后数据位宽变宽。这时候我们需要对数据进行截位。这时候需要读取coe文件求和后&#xff0c;计算我们需要截位的位…

Postman之版本信息查看

Postman之版本信息查看 一、为何需要查看版本信息&#xff1f;二、查看Postman的版本信息的步骤 一、为何需要查看版本信息&#xff1f; 不同的版本之间可能存在功能和界面的差异。 二、查看Postman的版本信息的步骤 1、打开 Postman 2、打开设置项 点击页面右上角的 “Set…

数据加密、文档加密为什么都选择安企神软件

数据加密、文档加密为什么都选择安企神软件 免费试用安企神 在数据加密和文件加密领域&#xff0c;有众多优秀的软件&#xff0c;他们功能各异、价格不同、效果也大相径庭&#xff0c;经过对比使用、用户口碑和技术网站评判&#xff0c;安企神在各方面都稳坐第一把交易。其原…

笔记强训 || NC313 两个数组的交集 || 哈希表/去重+排序+遍历查找+插入ret

题目解析 两个不同整数数组&#xff0c;其中两个数组均是无序且有多个重复项。找到两个数组中的公共元素并返回。此时&#xff0c;需要注意&#xff0c;返回值中并没有重复项&#xff0c;也就是如果数据均一致&#xff0c;返回一个数字即可。 算法原理 思路 就是将一个数组…

【编程TOOL】VC++6.0下载安装配置使用保姆式教程

目录 ​编辑 1.软件介绍 2.软件下载 3.软件安装 3.1.下载得到可执行文件并双击进行安装 3.2. 点击下一步 3.3. 选择安装位置 3.4. 勾选“创建桌面快捷方式”并点击下一步 5. 点击安装并等待 3.6. 先取消运行&#xff0c;后点击完成&#xff0c;软件即安装完毕 4.兼容性配置 4.1…

代码随想录算法训练营DAY28(记录)|C++回溯算法Part.5|491.递增子序列、46.全排列、47.全排列II

文章目录 491.递增子序列思路伪代码CPP代码优化代码 46.全排列思路伪代码CPP代码 47.全排列IICPP代码 491.递增子序列 力扣题目链接 文章链接&#xff1a;491.递增子序列 视频连接&#xff1a;回溯算法精讲&#xff0c;树层去重与树枝去重 | LeetCode&#xff1a;491.递增子序列…

零基础小白,如何入门计算机视觉?

目录 前言 计算机视觉技术学习路线 基础知识 1. 数学基础 2. 编程基础 3. 图像处理基础 基础算法与技术 1. 特征提取与描述符 2. 图像分割与对象检测 3. 三维重建与立体视觉 机器学习与深度学习 1. 机器学习基础 2. 深度学习 高级主题与应用 1. 高级机器学习与深度学习 2. 计算…

2024年MathorCup数模竞赛C题问题一二+部分代码分享

C题持续更新中 问题一问题二代码混合ARIMA-LSTM模型构建完整数据与代码第一问第二问 问题一 问题一要求对未来30天每天及每小时的货量进行预测。首先&#xff0c;利用混合ARIMA-LSTM模型进行时间序列预测。ARIMA模型擅长捕捉线性特征和趋势&#xff0c;而LSTM模型处理非线性关…

[stm32]DMA使用

自动重装和M2M(软件trig)不能一起使用&#xff0c;否则会停不下来 void MyDMA_Init(uint32_t AddrA,uint32_t AddrB,uint16_t Size){RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1,ENABLE);DMA_InitTypeDef DMA_InitStructure;DMA_InitStructure.DMA_PeripheralBaseAddrAddrA;//外…

基于SpringBoot+Vue的校园网上店铺的设计与实现(源码+文档+包运行)

一.系统概述 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统校园店铺商品销售信息管理难度大&#xff0c;容错率…

c++取经之路(其六)——类与对象初始化列表,类的隐式转换,explict,static修饰成员

今天我们来讲一些很散的东西&#xff0c;通过这些很散的东西我们可以使我们之前学的东西更加通透&#xff0c;基本上把这些知识搞定&#xff0c;类与对象的知识基本上就差不多掌握了。 初始化列表&#xff1a; 定义&#xff1a;以一个冒号开始&#xff0c;接着是一个以逗号分…

Python景区票务人脸识别系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

Facade 外观

意图 为子系统中的一组接口提供一个一致的界面&#xff0c;Facade模式定义了一个高层接口&#xff0c;这个接口使得这一字系统更加容易使用。 结构 其中&#xff1a; Facade知道哪些子系统负责处理请求&#xff1b;将客户的请求代理给适当的子系统对象。 Subsystem classes…

Ai2024安装包(亲测可用)

目录 一、软件简介 二、软件下载 一、软件简介 Adobe illustrator&#xff0c;常被称为“AI”&#xff0c;是一种应用于出版、多媒体和在线图像的工业标准矢量插画的软件。作为一款非常好的矢量图形处理工具&#xff0c;该软件主要应用于印刷出版、海报书籍排版、专业插画、多…

大数据测试:构建Hadoop和Spark分布式HA运行环境

随着大数据技术的不断发展&#xff0c;Hadoop和Spark已成为处理大规模数据的热门框架。在生产环境中&#xff0c;高可用性&#xff08;HA&#xff09;是至关重要的&#xff0c;以确保数据处理和分析任务不受中断。本文将详细介绍如何构建 Hadoop和Spark分布式HA运行环境&#x…

HarmonyOS开发实例:【任务延时调度】

介绍 本示例使用[ohos.WorkSchedulerExtensionAbility] 、[ohos.net.http]、[ohos.notification] 、[ohos.bundle]、[ohos.fileio] 等接口&#xff0c;实现了设置后台任务、下载更新包 、保存更新包、发送通知 、安装更新包实现升级的功能。 效果预览 使用说明 安装本应用之…

30K上岸,转鸿蒙开发之后直接乱杀!!

互联网太卷了&#xff0c;熬过了2023才发现&#xff0c;2024更难熬&#xff01;只因行业发展多年&#xff0c;人才过度饱和&#xff01;那前端的出路在哪里&#xff1f;我推荐大家学【华为鸿蒙原生应用开发】新兴行业需求大&#xff0c;各大厂都在高薪抢人&#xff0c;然后前端…

数据的表示和运算—2

1.算术逻辑单元(ALU) 输入信号:A和B为要进行计算的两个操作数。(本质上就是高低电频电信号) 输出信号:输出运算结果 控制信号:由控制单元(CU)发出&#xff0c;解析指令的含义&#xff0c;解析完发出控制信号&#xff0c;M表示做什么运算,M1(逻辑运算) M0(算术运算) S0 ~ S3指明…

Vue3从入门到实战:深度掌握组件通信(下部曲)

5.组件通信方式5-$attrs $attrs的概念&#xff1a; 在Vue中&#xff0c;$attrs 是一个特殊的属性&#xff0c;用于访问父组件向子组件传递的非特定属性。它可以让子组件轻松地获取父组件传递的属性&#xff0c;而无需在子组件中显式声明这些属性。 想象一下你有一个父组件和…

vue3第二十节(新增编译宏defineModel)

为什么会需要使用defineModel() 注意&#xff1a;defineModel() 需要在3.4及以上版本才可使用&#xff1b; 组件之间通讯&#xff0c;通过 props 和 emits 进行通讯,是单向数据流&#xff0c;比如&#xff1a;props是自上而下的&#xff08;父组件数据修改导致子组件更新&…