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

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

常用命令使用规则

组件编写方式:

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.mfbz.cn/a/553004.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UE5 C++ 射线检测

一.声明四个变量 FVector StartLocation;FVector ForwardVector;FVector EndLocation;FHitResult HitResult;二.起点从摄像机&#xff0c;重点为摄像机前9999m。射线检测 使用LineTraceSingleByChannel 射线直线通道检测&#xff0c;所以 void AMyCharacter::Tick(float Delt…

GPT国内能用吗

2022年11月&#xff0c;Open AI发布ChatGPT&#xff0c;ChatGPT展现了大型语模型在自然语言处理方面的惊人进步&#xff0c;其生成文本的流畅度和连贯性令人印象深刻&#xff0c;为AI应用打开了新的可能性。 ChatGPT的出现推动了AI技术在各个领域的应用&#xff0c;例如&#x…

Python学习教程(Python学习路线+Python学习视频):Python数据结构

数据结构引言&#xff1a; 数据结构是组织数据的方式&#xff0c;以便能够更好的存储和获取数据。数据结构定义数据之间的关系和对这些数据的操作方式。数据结构屏蔽了数据存储和操作的细节&#xff0c;让程序员能更好的处理业务逻辑&#xff0c;同时拥有快速的数据存储和获取方…

.net9 AOT编绎生成标准DLL,输出API函数教程-中国首创

1&#xff0c;安装VS2022预览版&#xff08;Visual Studio Preview&#xff09; https://visualstudio.microsoft.com/zh-hans/vs/preview/#download-preview 2&#xff0c;选择安装组件&#xff1a;使用C的桌面开发 和 .NET桌面开发 ------------------------------------- …

java八股文知识点讲解(个人认为讲的比较好的)

1、解决哈希冲突——链地址法&#xff1a;【第7章查找】19哈希表的查找_链地址法解决哈希冲突_哔哩哔哩_bilibili 2、解决哈希冲突——开放地址法 &#xff1a; 【第7章查找】18哈希表的查找_开放定址法解决哈希冲突_哔哩哔哩_bilibili 3、小根堆大根堆的创建&#xff1a;选择…

【每日刷题】Day17

【每日刷题】Day17 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. 19. 删除链表的倒数第 N 个结点 - 力扣&#xff08;LeetCode&#xff09; 2. 162. 寻找峰值 - 力扣…

1 回归:锂电池温度预测top2 代码部分(一) Tabnet

2024 iFLYTEK A.I.开发者大赛-讯飞开放平台 TabNet&#xff1a; 模型也是我在这个比赛一个意外收获&#xff0c;这个模型在比赛之中可用。但是需要GPU资源&#xff0c;否则运行真的是太慢了。后面针对这个模型我会写出如何使用的方法策略。 比赛结束后有与其他两位选手聊天&am…

《ElementPlus 与 ElementUI 差异集合》el-popconfirm 气泡确认框之插槽写法有差异

ElementUI 直接在 el-button 上配置属性 slot&#xff1b; <el-popconfirm title"确定删除吗&#xff1f;请谨慎操作&#xff01;" confirm"delete"><el-button slot"reference" size"small" type"danger">删…

Word学习笔记之奇偶页的页眉与页码设置

1. 常用格式 在毕业论文中&#xff0c;往往有一下要求&#xff1a; 奇数页右下角显示、偶数页左下角显示奇数页眉为每章标题、偶数页眉为论文标题 2. 问题解决 2.1 前期准备 首先&#xff0c;不论时要求 1、还是要求 2&#xff0c;这里我们都要做一下设置&#xff1a; 鼠…

Adobe Firefly是否将重新定义AI视频编辑领域?|TodayAI

Adobe最近发布了一段令人瞩目的视频&#xff0c;详细展示了其最新推出的Adobe Firefly视频模型。这一模型集成了尖端的生成式人工智能技术&#xff0c;带来了一系列颠覆性的视频编辑功能&#xff0c;引发了业界的广泛关注和讨论。 视频中的旁白充满热情地宣布&#xff1a;“Ad…

【超级简单】vscode进入服务器的docker容器

前提 1、已经运行docker容器 2、已经用vscode链接服务器 在vscode中安装的插件 Dev Containers docker 在容器中安装的依赖 yum install openssh-server yum install openssh-clientsvscode进入服务器的docker容器 找到自己的容器&#xff0c;右键点击&#xff0c;找到…

Jmeter BeanShell调用Java方法加密

1、添加BeanShell前置处理器 由于请求接口时&#xff0c;会传加密参数。加密过程会在请求之前完成&#xff0c;所以需要使用前置处理器中beanshell preprocessor 2、编写BeanShell脚本 ①定义一个beashell变量&#xff1a;phoneNum&#xff0c;在Beanshell中可以直接调用Jmete…

idea运行报错:启动命令过长

JAVA项目&#xff0c;运行的时候报错 Command line is too long. Shorten the command line via JAR manifest or via a classpath file and rerun老问题了&#xff0c;记录一下 解决办法&#xff1a; 1、Edit Configurations 2、点击Modify options设置&#xff0c;勾选S…

janus架构学习

基础介绍 Janus 是由Meetecho设计和开发的开源、通用的基于SFU架构的WebRTC流媒体服务器&#xff0c;它支持在Linux的服务器或MacOS上的机器进行编译和安装。Janus 是使用C语言进行编写的&#xff0c;它的性能十分优秀。 架构 janus为sfu架构 模块结构图 模块说明 core模…

elementui 弹窗展示自动校验表单项bug

表单校验失败一次之后&#xff0c;再次弹出表单&#xff0c;触发自动校验 解决方案&#xff1a; clearValidate() 方法清空表单校验项 this.$nextTick(() > {this.$refs[checkForm].clearValidate() }) 使用nextTick规避报错

chroot -- 限制其他用户liunx空间

目录- 限制其他用户liunx空间 前言开始进入监狱总结 前言 前提 ecs 服务器&#xff0c;centos系统&#xff0c;乌班图系统需要root榕湖 开始 首先&#xff0c;登录到您的ECS机器。创建一个新用户&#xff1a; 使用 adduser 命令创建一个新用户。例如&#xff0c;要创建一个名…

k8s之etcd

1.特点&#xff1a; etcd 是云原生架构中重要的基础组件。有如下特点&#xff1a; 简单&#xff1a;安装配置简单&#xff0c;而且提供了 HTTP API 进行交互&#xff0c;使用也很简单键值对存储&#xff1a;将数据存储在分层组织的目录中&#xff0c;如同在标准文件系统中监…

图像分类:Pytorch实现Vision Transformer(ViT)进行图像分类

图像分类&#xff1a;Pytorch实现Vision Transformer&#xff08;ViT&#xff09;进行图像分类 前言相关介绍ViT模型的基本原理&#xff1a;ViT的特点与优势&#xff1a;ViT的缺点&#xff1a;应用与拓展&#xff1a; 项目结构具体步骤准备数据集读取数据集设置并解析相关参数定…

Vue3项目 网易严选_学习笔记

Vue3项目 网易严选_第一天 主要内容 项目搭建vuex基础路由设计首页顶部和底部布局 学习目标 知识点要求项目搭建掌握vuex基础掌握路由设计掌握首页顶部和底部布局掌握 一、项目搭建 1.1 创建项目 vue create vue-wangyi选择vue3.0版本 1.2 目录调整 大致步骤&#xff…

计算机网络 TCP/IP体系 物理层

一. TCP/IP体系 物理层 1.1 物理层的基本概念 物理层作为TCP/IP网络模型的最低层&#xff0c;负责直接与传输介质交互&#xff0c;实现比特流的传输。 要完成物理层的主要任务&#xff0c;需要确定以下特性&#xff1a; 机械特性&#xff1a;物理层的机械特性主要涉及网络…
最新文章