重庆南岸营销型网站建设公司哪家好/网络服务商主要包括

重庆南岸营销型网站建设公司哪家好,网络服务商主要包括,金融投资管理公司网站源码,结构设计网站setState详解 实现原理 开发中我们并不能直接修改State来重新渲染界面: 因为修改State之后,希望React根据最新的State来重新渲染界面,但这种方式的修改React并不知道数据发生了变化; React并没有类似于Vue2中的Object.defineP…

setState详解

实现原理

开发中我们并不能直接修改State来重新渲染界面:

因为修改State之后,希望React根据最新的State来重新渲染界面,但这种方式的修改React并不知道数据发生了变化;

React并没有类似于Vue2中的Object.defineProperty或Vue3中的Proxy的方式来监听数据的变化;

我们必须通过setState来告知React数据已经发生了变化;

该方法的源码实现如下:

三种使用方式

import React, { Component } from 'react'export class App extends Component {constructor () {super () this.state={message:'hello',count:20}}changeText() {// 1.setState更多用法// 1.1基本使用// this.setState({//   message:'你好'// })/* 1.2setState可以传入一个回调函数好处一:可在回调函数中编写新的state处理逻辑好处二:当前回调函数会将之前的state和props传递进来*/// this.setState((state,props) => {//   console.log(state,props);//   return {//     message:'你好'//   }// })/* 1.3setState在React的事件处理中是一个异步调用如果希望在数据更新之后(数据合并),获取到对应的结果执行一些逻辑代码那么可以在setState中传入第二个参数:callback*/this.setState({message:"你好呀,小橙子"},() => {console.log(this.state.message);//你好呀,小橙子})// 会先执行这行代码console.log("-----------",this.state.message);// hello}addCount () {}render() {const { message,count } = this.statereturn (<div><h2>{message}</h2><button onClick={() => this.changeText()}>修改文本</button><h2>当前计数:{count}</h2><button onClick={() => this.addCount()}>count+1</button></div>)}
}export default App

setState异步更新

为什么setState设计为异步呢?

React核心成员(Redux的作者)Dan Abramov也有对应的回复:RFClarification: why is `setState` asynchronous? · Issue #11527 · facebook/react · GitHub

  1. setState设计为异步,可以显著的提升性能;
  • 如果每次调用 setState都进行一次更新,那么意味着render函数会被频繁调用,界面重新渲染,这样效率是很低的;
  • 最好的办法应该是获取到多个更新,之后进行批量更新;
  1. 如果同步更新了state,但是还没有执行render函数,那么state和props不能保持同步;
  • state和props不能保持一致性,会在开发中产生很多的问题;
import React, { Component } from 'react'
function Hello (props) {return <h2>{props.message}</h2>
}export class App extends Component {constructor () {super () this.state={message:'hello',count:20}}changeText() {}addCount () {// 一直是20+1——也说明setState是异步的/* this.setState({count:this.state.count + 1})this.setState({count:this.state.count + 1})this.setState({count:this.state.count + 1}) */this.setState((state) => {console.log(this.state.count);//20return {count:state.count + 1}})this.setState((state) => {console.log(this.state.count);//20return {count:state.count + 1}})this.setState((state) => {console.log(this.state.count);//20return {count:state.count + 1}})}/* 假设setState是同步的,那么点击按钮后,this.state.message已经改变——但是还未执行render函数——那么页面上的数据就还是之前的-即state和props不能保持同步*/render() {// 调用addCount函数,里面有三个setState,但render只会重新渲染一次——批量更新console.log("render函数被执行了几次");const { message,count } = this.statereturn (<div><h2>{message}</h2><button onClick={() => this.changeText()}>修改文本</button><h2>当前计数:{count}</h2><button onClick={() => this.addCount()}>count+1</button><Hello message={message} /></div>)}
}export default App

如何获取异步修改完的结果?

方式一:setState的回调

setState接受两个参数:第二个参数是一个回调函数,这个回调函数会在更新后会执行;

方式二:生命周期函数

注意:在React18之前,如果在setState外边包个setTimeout这种宏任务,它不由React回调,而是浏览器。故setState就变成了同步操作

React18之前:setTimeout中setState操作,是同步操作
React18之后:setTimeout中setState操作,是异步操作
setTimeout ( () => {this.setState({message:'你好'})console.log(this.state.message);//React18之前:你好;React18之后:hello
},0) 

性能优化SCU

当我们修改根组件中的数据,所有组件都需要重新render,进行diff算法,性能极低!——只更新数据改变的即可——通过shouldComponentUpdate方法

//nextProps:修改之后最新的props; nextState:修改之后最新的state
shouldComponentUpdate(nextProps, nextState) {// 性能优化:自己对前后state进行对比,如果前后state没有变化,就不更新组件if(this.state.message !== nextState.message  || this.state.count !== nextState.count){return true}//根据返回值觉得是否调用render方法return false
}

但如果所有的类都需要手动设置,那工作量也太大了!

React内部已帮我们实现PureComponent

底层原理实现:

注意:PureComponent只能检测第一层数据的变化,也就是复杂数据类型若地址未发生变化,是检测不到的

import React, { PureComponent } from 'react'export default class App extends PureComponent {constructor () {super()this.state = {books:[{name:"你不知道的JS",price:99,count:2},{name:"JS高级程序设计",price:78,count:2},{name:"React高级设计",price:94,count:2},{name:"LeetCode",price:88,count:2},]}}/* PureComponent底层实现原理:shouldComponentUpdate(nextProps,nextState) {浅层比较return (!shallowEqual(nextProps,this.props) || shallowEqual(nextState,this.state))}*/addBook() {const newBook = {name:"算法",price:99,count:8}/* React 依赖于状态的不可变性来确定何时需要更新 UI直接修改状态对象的属性不会让 React 知道状态已经发生了变化,因此不会重新渲染组件该做法在PureComponent中是不能引起重新渲染的this.state.books.push(newBook)  */this.setState({books:[...this.state.books,newBook]})}addCount (index) {// this.state.books[index]++   //引用对象并未发生改变const newBooks = [...this.state.books]//引用发生改变newBooks[index].count++this.setState({books:newBooks})}render() {const {books} = this.statereturn (<div><h2>书籍列表</h2><ul>{books.map((item,index) => {return (<li key={item.name}><span>{item.name}-{item.price}-{item.count}</span><button onClick={() => this.addCount(index)}>+1</button></li>)})}</ul><button onClick={() => this.addBook()}>添加新书籍</button></div>)}
}

针对类组件可使用 PureComponent。那函数组件那???

我们可使用高阶函数memo将组件都包裹一层

import { memo } from "react";
const Profile = memo(function(props) {console.log("Profile render函数");return (<div><h2>Profile-{props.message}</h2></div>)
})export default Profile

ref获取元素或组件实例

传入一个对象

1.类组件:通过 React.createRef() 创建 ref 对象,并绑定到 JSX 元素的 ref 属性

class ClassComponent extends React.Component {constructor(props) {super(props);this.myRef = React.createRef(); // 创建 ref 对象}componentDidMount() {console.log(this.myRef.current); // 获取 DOM 元素}render() {return <div ref={this.myRef}>类组件中使用 ref 对象</div>;}
}

2.函数组件:通过 React.useRef() Hook 创建 ref 对象,并绑定到 JSX 元素

function FunctionComponent() {const myRef = React.useRef(null); // 创建 ref 对象React.useEffect(() => {console.log(myRef.current); // 获取 DOM 元素}, []);return <div ref={myRef}>函数组件中使用 useRef</div>;
}

使用回调 ref

原理:将回调函数传递给元素的 ref 属性,React 在挂载/卸载时调用该回调,参数为 DOM 元素

1.类组件

class ClassComponent extends React.Component {constructor(props) {super(props);this.myRef = null; // 直接保存 DOM 引用}componentDidMount() {console.log(this.myRef); // 直接访问 DOM 元素}render() {return (<div ref={(el) => { this.myRef = el; }}> {/* 回调 ref */}类组件中使用回调 ref</div>);}
}

2.函数组件:

function FunctionComponent() {const myRef = React.useRef(null); // 持久化保存 DOM 引用const setRef = (el) => {myRef.current = el; // 通过回调更新 ref};React.useEffect(() => {console.log(myRef.current); // 获取 DOM 元素}, []);return <div ref={setRef}>函数组件中使用回调 ref</div>;
}

获取函数子组件的DOM

import React, { PureComponent, createRef,forwardRef } from 'react'const HelloWorld = forwardRef(function(props,ref) {return(<h1 ref={ref}>Hello World</h1>)
})export class App extends PureComponent {constructor(props) {super(props);this.whyRef = createRef();}getNativeDOM(){console.log(this.whyRef.current);}render() {return (<div>{/* 不能在函数组件上直接使用 ref属性,因为他们没有实例——通过forwardRef做一个转发*/}<HelloWorld ref={this.whyRef}/><button onClick={() => this.getNativeDOM()}>获取组件实例</button></div>)}
}export default App

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

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

相关文章

SSH密钥认证 + 文件系统权限控制 + Git仓库配置+封存与解封GIT仓库

在本地服务器上实现多个用户仅通过git push操作修改仓库、禁止其他改写方式的需求&#xff0c;可以通过以下步骤实现&#xff1a; 方法概述 通过SSH密钥认证 文件系统权限控制 Git仓库配置&#xff0c;确保用户仅能通过git push命令提交修改&#xff0c;而无法通过直接操作服…

C++11中智能指针的使用(shared_ptr、unique_ptr、weak_ptr)

C11中智能指针的使用(shared_ptr、unique_ptr、weak_ptr) 一、shared_ptr原理 shared_ptr 是另一种智能指针&#xff0c;用于实现多个 shared_ptr 实例共享同一个对象的所有权。它通过内部的控制块&#xff08;通常是一个包含计数器和指向对象的指针的结构&#xff09;来管理…

2024年认证杯SPSSPRO杯数学建模B题(第二阶段)神经外科手术的定位与导航全过程文档及程序

2024年认证杯SPSSPRO杯数学建模 B题 神经外科手术的定位与导航 原题再现&#xff1a; 人的大脑结构非常复杂&#xff0c;内部交织密布着神经和血管&#xff0c;所以在大脑内做手术具有非常高的精细和复杂程度。例如神经外科的肿瘤切除手术或血肿清除手术&#xff0c;通常需要…

尝试在软考62天前开始成为软件设计师-信息系统安全

安全属性 保密性:最小授权原则(能干活的最小权限)、防暴露(隐藏)、信息加密、物理保密完整性(防篡改):安全协议、校验码、密码校验、数字签名、公证 可用性:综合保障( IP过滤、业务流控制、路由选择控制、审计跟踪)不可抵赖性:数字签名 对称加密 DES :替换移位 3重DESAESR…

Rocky9.5基于sealos快速部署k8s集群

首先需要下载 Sealos 命令行工具&#xff0c;sealos 是一个简单的 Golang 二进制文件&#xff0c;可以安装在大多数 Linux 操作系统中。 以下是一些基本的安装要求&#xff1a; 每个集群节点应该有不同的主机名。主机名不要带下划线。 所有节点的时间需要同步。 需要在 K8s …

Cursor软件如何刷新机器码流程

一.退出Cursor软件账号 打开Cursor软件&#xff0c;点击设置-->General-->Account-->Log out,现将Cursor软件上登录的账户退出。 二.将Cursor官网上登录的Cursor账户也清空掉 点击头像--> ACCOUNT SETTINGS -->Account-->Advanced-->Delete Account-->…

类与对象(中)(详解)

【本节目标】 1. 类的6个默认成员函数 2. 构造函数 3. 析构函数 4. 拷贝构造函数 5. 赋值运算符重载 6. const成员函数 7. 取地址及const取地址操作符重载 1.类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&…

React+Ant Design的Layout布局实现暗黑模式切换

目录 效果预览完整代码我遇到的BUG问题代码BUG1&#xff1a;暗黑模式下内容区不变成深色BUG2&#xff1a;光亮模式下的左右区域是深色 补充知识ConfigProvider是什么&#xff1f;Ant Design中的theme如何使用&#xff1f;theme 配置的常见字段主题算法通过 useToken 获取主题 效…

力扣DAY24 | 热100 | 回文链表

前言 简单 √ 是反转链表的衍生题&#xff0c;很快写完了。不过没考虑到恢复链表结构的问题。 题目 给你一个单链表的头节点 head &#xff0c;请你判断该链表是否为回文链表。如果是&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 示例 1&#xff1a; 输…

【GL010】C++

1.C中的const关键字有哪些用法&#xff1f; 1.修饰变量&#xff1a;表示变量的值不可修改。 const int a 10; 2.修饰指针&#xff1a; const int* p&#xff1a; // 指针指向的内容不可修改。 int* const p&#xff1a; // 指针本身不可修改。 const int* const…

金融行业 UE/UI 设计:解锁高效体验,重塑行业界面

在数字化浪潮中&#xff0c;金融行业的竞争日益激烈&#xff0c;用户体验&#xff08;UE&#xff09;和用户界面&#xff08;UI&#xff09;设计成为企业脱颖而出的关键。兰亭妙微凭借丰富的经验和创新的方法&#xff0c;为金融行业打造了一套行之有效的 UE/UI 解决方案&#x…

C语言字符函数,字符串函数以及内存函数

那么博主写这一片博客的目的就是为下一篇c的string类做铺垫&#xff0c;那么下面就请期待博主的下一篇文章吧。 目录 1.字符函数 2.字符串函数&#xff08;均在string.h头文件中&#xff09; strlen的使用和模拟实现 strcpy 的使用和模拟实现 strcat 的使用和模拟实现 s…

【Linux】同步原理剖析及模拟BlockQueue生产消费模型

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;博客仓库&#xff1a;https://gitee.com/JohnKingW/linux_test/tree/master/lesson &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &…

<数据集>轨道异物识别数据集<目标检测>

数据集下载链接&#xff1a;https://download.csdn.net/download/qq_53332949/90527370 数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;1659张 标注数量(xml文件个数)&#xff1a;1659 标注数量(txt文件个数)&#xff1a;1659 标注类别数&#xff1a;6 标注类别…

LabVIEW液压振动锤控制系统

在现代工程机械领域&#xff0c;液压振动锤的高效与精准控制日益显得重要。本文通过LabVIEW软件&#xff0c;展开液压振动锤启停共振控制技术的研究与应用&#xff0c;探讨如何通过改进控制系统来优化液压振动锤的工作性能&#xff0c;确保其在复杂工况下的稳定性与效率。 ​ …

【开源宝藏】30天学会CSS - DAY7 第七课 CSS 关键帧打造Preloader 追逐动画

你的代码实现了一个 方形轨迹预加载动画&#xff08;Preloader Animation&#xff09;&#xff0c;其中三个 span 元素沿着一个 22 网格 轨迹循环移动。现在&#xff0c;我们将 拆解核心实现步骤&#xff0c;让你能一步步理解并调整动画效果。 第 0 步&#xff1a;项目概览 你…

GPT-SoVITS本地部署:低成本实现语音克隆远程生成音频全流程实战

文章目录 前言1.GPT-SoVITS V2下载2.本地运行GPT-SoVITS V23.简单使用演示4.安装内网穿透工具4.1 创建远程连接公网地址 5. 固定远程访问公网地址 前言 今天要给大家安利一个绝对能让你大呼过瘾的声音黑科技——GPT-SoVITS&#xff01;这款由花儿不哭大佬精心打造的语音克隆神…

JVM(基础篇)

一.初识JVM 1.什么是JVM JVM全称Java Virtyal Machine&#xff0c;中文译名 Java虚拟机 。JVM本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件(将字节码解释成机器码)。 2.JVM的功能 解释和运行&#xff1a;对字节码文件中的指令号&#xff0c;实时…

【高并发内存池】第四弹---深入理解PageCache:整体设计、核心实现及Span获取策略详解

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】【Linux网络编程】【项目详解】 目录 1、pagecache 1.1、整体设计 1.2、核心实现 1.3、获取Span 1.3.1、获取一个非空的Span 1.3…

深入理解C语言数据结构之快速排序三路划分

在数据结构和算法的世界里&#xff0c;排序算法是基石一般的存在。快速排序作为一种高效的排序算法&#xff0c;以其平均情况下的优秀时间复杂度而被广泛应用。今天&#xff0c;让我们深入探讨快速排序的一种变体——三路划分的快速排序&#xff0c;看看它是如何在C语言中施展魔…