React hooks文档笔记(二) 添加交互性

news2024/11/25 14:23:47

添加交互性

  • 1. 事件传播
    • 1.1 停止传播
    • 1.2 阻止默认事件
  • 2. [Hook] useState 状态
  • 3. 渲染和提交
    • 3.1 触发渲染
    • 3.2 React渲染组件
    • 3.3 提交对 DOM 的更改
    • 3.4 浏览器绘制
  • 4. 渲染快照
    • 状态队列例子
  • 5. 更新state中的对象

1. 事件传播

js的事件流:

  • 事件捕获:从外到内
  • 事件冒泡:从内到外(默认模式)
export default function Toolbar() {
  return (
    <div className="Toolbar" onClick={() => {
      alert('You clicked on the toolbar!');
    }}>
      <button onClick={() => alert('Playing!')}>
        Play Movie
      </button>
      <button onClick={() => alert('Uploading!')}>
        Upload Image
      </button>
    </div>
  );
}

点击任一按钮,它的 onClick 将首先运行,然后是父节点

的 onClick—— 所以会出现两条消息。
在这里插入图片描述
在这里插入图片描述 在这里插入图片描述如果你点击灰色区域本身,只有父
的 onClick 会运行。

1.1 停止传播

为阻止传播,可以在onClick中加一行引用事件参数e并调用e.stopPropagation()方法,此时当用户点击<button>时触发器该条语句,停止事件向外扩散,父节点<div>的onClick将不再触发。

1.2 阻止默认事件

e.preventDefault() 阻止默认行为
<form>:当内部按钮点击后,将默认重载整个页面

export default function Signup() {
  return (
    <form onSubmit={e => {
      e.preventDefault();    //点击按钮后将不再重载页面
      alert('Submitting!');
    }}>
      <input />
      <button>Send</button>
    </form>
  );
}

2. [Hook] useState 状态

形式:const [index, setIndex] = useState(默认值)

“[]”从useState解构出来两部分,

  1. 用于保留渲染之间数据的状态变量index
  2. 一个状态设置函数,setIndex用于更新变量触发 React 再次渲染组件

只能使用在组件,不能在条件、循环或其他嵌套函数中调用 Hooks,hook调用原理:
React报错#310复盘小结+hooks使用的场景+调用原理

只有 Hook 的调用顺序在多次渲染之间保持一致,React 才能正确地将内部 state 和对应的 Hook 进行关联。

useState内部:

React 为每个组件保存一组状态对。 它还维护当前对索引,该索引在渲染前设置为 0。 每次调用 useState 时,React 都会为您提供下一个状态对并递增索引。

let componentHooks = [];
let currentHookIndex = 0;
// How useState works inside React (simplified).
function useState(initialState) {
  let pair = componentHooks[currentHookIndex];
  if (pair) {
    // This is not the first render,
    // so the state pair already exists.
    // Return it and prepare for next Hook call.
    currentHookIndex++;
    return pair;
  }

  // This is the first time we're rendering,
  // so create a state pair and store it.
  pair = [initialState, setState];

  function setState(nextState) {
    // When the user requests a state change,
    // put the new value into the pair.
    pair[0] = nextState;
    updateDOM();
  }

  // Store the pair for future renders
  // and prepare for the next Hook call.
  componentHooks[currentHookIndex] = pair;
  currentHookIndex++;
  return pair;
}

3. 渲染和提交

举个例子:

组件是厨房里的厨师,用食材烹制美味佳肴。React 是一个服务员,负责接收客户的订单并为他们带来菜肴。这个请求和提供 UI 的过程分为三个步骤:

  1. 触发渲染(将客人的订单送到厨房)
  2. 渲染组件(在厨房准备订单)
  3. 提交给 DOM(将制作好的菜肴放在客户的桌上)
    在这里插入图片描述

3.1 触发渲染

组件渲染有两个原因:

  1. 初始渲染
    root.render(<App />);

  2. 组件(或其祖先之一)的state已更新

3.2 React渲染组件

export default function Gallery() {
  return (
    <section>
      <h1>Inspiring Sculptures</h1>
      <Image />
      <Image />
    </section>
  );
}
function Image() {
  return (
    <img src="xxx" alt="xxx" />
  );
}
  • 在初始渲染时,React 将调用根组件。
    <section><h1> 和两个<img>标签创建DOM节点

  • 对于后续的渲染,React 将调用状态更新触发渲染的函数组件
    React 将计算它们的哪些属性(如果有)自上次渲染以来发生了变化。 在下一步,即提交阶段之前,它不会对这些信息做任何事情。

3.3 提交对 DOM 的更改

  • 初始渲染时,React 将使用appendChild() DOM API 将它创建的所有 DOM 节点放在屏幕上。
  • 对于重新渲染,React 将应用最少的必要操作(在渲染时计算!)以使 DOM 匹配最新的渲染输出。

如果渲染之间存在差异,React 只会更改 DOM 节点。

举例:
Clock组件会随着父节点传入不同的props 参数 time 而重新渲染,但在input中输入‘1’,重新渲染时‘1’没有消失。

export default function Clock({ time }) {
  return (
    <>
      <h1>{time}</h1>
      <input />
    </>
  );
}

在这里插入图片描述在这里插入图片描述

这是因为随着time的改变, React 只更新了<h1>的内容,而没有触及<input>

3.4 浏览器绘制

渲染完成并且 React 更新 DOM 后,浏览器将重新绘制屏幕

4. 渲染快照

当 React 重新渲染一个组件时:

  1. React 再次调用你的函数。
  2. 您的函数返回一个新的 JSX 快照(使用该渲染中的state计算的,在快照中保持状态值“固定”)
  3. React 然后更新屏幕以匹配您返回的快照。

在这里插入图片描述
setState 只会为下一次渲染更改它

export default function Counter() {
  const [number, setNumber] = useState(0);
  return (
    <>
      <h1>{number}</h1>
      <button onClick={() => {
        setNumber(number + 1);
        setNumber(number + 1);
      }}>+2</button>
    </>
  )
}

点击第一次后:
在这里插入图片描述
点击第二次后:
在这里插入图片描述
发现两次点击都只加了1

在第一次渲染期间,number是0,调用onClick:
第一个setNumber(number + 1)等价于 setNumber(0 + 1)
第二个setNumber(number + 1)等价于 setNumber(0 + 1)
React 准备在下一次渲染时更改number为1,也就是说设置状态为1了两次
在这里插入图片描述

在处理状态更新之前,React 会等到事件处理程序中的所有代码都已运行。这使您可以更新多个状态变量——甚至来自多个组件——而不会触发太多重新渲染

q: 在下一次渲染之前需要多次更新相同的state?


答: 可以传递一个函数,该函数根据前一个状态计算下一个状态队列
例如将上述例子替换为setNumber(n => n + 1);

n => n + 1更新函数(必须是纯函数并且只返回结果)

当您将它传递给状态设置器时:

  1. 在事件处理程序中的所有其他代码运行之后,React 将此函数排队等待处理。
  2. 在下一次渲染期间,React 遍历队列并为您提供最终的更新状态。
队列更新nreturns
n => n + 100+1=1
n => n + 111+1=2

状态队列例子

实现状态队列:https://codesandbox.io/s/0xym3z?file=/processQueue.js&utm_medium=sandpack

<button onClick={() => {
  setNumber(number + 5);
  setNumber(n => n + 1);
  setNumber(42);
}}>
队列更新nreturns
“replace with 5”0(unused)5
n => n + 155+1=6
“replace with 42”6(unused) 42

在下一次渲染期间,React 遍历状态队列:

  1. setNumber(number + 5): number是0,所以setNumber(0 + 5)。React 将“替换为5”添加到它的队列中。
  2. setNumber(n => n + 1): n => n + 1是一个更新函数。React 将该函数添加到它的队列中。
  3. setNumber(42): React 将“替换为42”添加到它的队列中。

5. 更新state中的对象

用 Immer 编写简洁的更新对象state逻辑:Immer编写简洁的更新state逻辑

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

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

相关文章

Spring学习(二)(Spring创建和使用)

经过前⾯的学习我们已经知道了&#xff0c;Spring 就是⼀个包含了众多⼯具⽅法的 IoC 容器。既然是容器那么 它就具备两个最基本的功能&#xff1a; 将对象(Bean)存储到容器&#xff08;Spring&#xff09;中&#xff1b; 从容器中将对象取出来。那么该怎么将Bean存储的Spring以…

单片机系统架构

单片机系统架构 单片机概述 微型计算机的组成 微处理器、存储器加上I/O接口电路组成微型计算机。各部分通过地址总线&#xff08;AB&#xff09;、数据总线&#xff08;DB&#xff09;和控制总线&#xff08;CB&#xff09;相连。 微型计算机的应用形态 ​ 从应用形态上&am…

python数据可视化-日期折线图画法

引入 什么是折线图&#xff1a; 折线图是排列在工作表的列或行中的数据可以绘制到折线图中。折线图可以显示随时间&#xff08;根据常用比例设置&#xff09;而变化的连续数据&#xff0c;因此非常适用于显示在相等时间间隔下数据的趋势。 在折线图中&#xff0c;类别数…

【vue】- 简易版筛选组件可展开/收起

仅做记录&#xff0c;未整理格式 css部分未完全&#xff0c;每个筛选条件为固定宽度 实现效果 单行筛选条件时不触发更多按钮&#xff0c;且做占位处理 多行筛选条件时默认收起 同时设定最大/最小宽度并监听该组件宽度变化 filter.vue组件 <template><div :cla…

c#调用c++ dll,Release版本内存访问错误

最近遇到个比较经典的案例&#xff0c;在c#中调用yara进行文件检测&#xff0c;yara是c编写的一个非常强大库&#xff0c;github有个大佬用c#对其进行了封装&#xff0c;使其能在跨平台下&#xff0c;只需编译yara的so或dll就能直接跑。但总是在Release版本下时不时就崩溃&…

Hadoop 组成

4 Hadoop 优势(4 高) 1)高可靠性:Hadoop底层维护多个数据副本,所以即使Hadoop某个计算元素或存储出现故障,也不会导致数据的丢失。 2)高扩展性:在集群间分配任务数据,可方便的扩展数以千计的节点。 3)高效性:在MapReduce的思想下,Hadoop是并行工作的,以加快任务…

低代码平台在ERP软件中的作用

很多人认为 低代码开发平台的出现颠覆了传统的软件开发模式&#xff0c;对软件开发行业造成冲击&#xff0c;其实低代码开发平台的出现只是提高了软件开发的效率&#xff0c;并不是要颠覆软件开发的模式。低代码平台在erp软件开发中的作用还是比较明显的。下面一起来了解一下相…

Postman Mock快速入门

目录 前言&#xff1a; 1.Mock简介 1.1 Mock定义 1.2 Mock目的 1.3 Mock意义 1.4 Mock服务 2. Postman 创建Mock服务 2.1 创建Mock服务 2.2 Postman创建Mock服务 2.2.1 Postman 创建Mock服务器参数 2.2.2 Postman创建Mock步骤 3.访问Postman Mock服务 前言&#xf…

css基础知识十三:怎么理解回流跟重绘?什么场景下会触发?

一、是什么 在HTML中&#xff0c;每个元素都可以理解成一个盒子&#xff0c;在浏览器解析过程中&#xff0c;会涉及到回流与重绘&#xff1a; 回流&#xff1a;布局引擎会根据各种样式计算每个盒子在页面上的大小与位置重绘&#xff1a;当计算好盒模型的位置、大小及其他属性…

MySQL-SQL全部锁详解(下)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a; 小刘主页 ♥️努力不一定有回报&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️学习两年总结出的运维经验&#xff0c;以及思科模拟器全套网络实验教程。专栏&#xf…

老PM,到底在牛什么?

早上好&#xff0c;我是老原。 “成长为一名优秀的项目经理。”相信这是每一个刚入行的项目经理都会立的flag。 对于项目经理来说&#xff0c;这是一个能力和经验并重的岗位&#xff0c;你应该也经常听人说&#xff0c;这项目经理是一个越老越吃香的职业。 就拿我自己来说&a…

【java】HashMap扩容机制详解

文章目录 JDK1.7下的扩容机制JDK1.8下的扩容机制 JDK1.7下的扩容机制 JDK1.7下的resize()方法是这样的&#xff1a; void resize(int newCapacity) { Entry[] oldTable table; int oldCapacity oldTable.length; if (oldCapacity MAXIMUM_CAPACITY) { threshold Integer.…

零样本视频生成无压力,基于飞桨框架实现Text2Video-Zero核心代码及依赖库

项目背景 继 AI 绘画之后&#xff0c;短视频行业正迎来 AI 智能创作的新浪潮。AI 智能创作正在各个方面为创作者和用户带来新的体验和价值。AI 动漫视频、AI 瞬息宇宙、AI 视频风格化等诸多创作功能不仅为视频内容创作提供了全新灵感&#xff0c;而且大大降低了用户创作的门槛…

SpringMVC原理分析 | 数据处理:ModelAndView

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 重定向和转发 ModelAndView 设置ModelAndView对象&#xff0c;根据view的名称、视图解析器跳转到指定的页面 页面&#xff1a;{视图解析器前缀} viewName {视图解析器…

git常用命令之命令集

15. 命令集 场景1. 构造1个文件的10个commit 命令作用for i in {1..10}; do date >> 66.txt && git add . && git commit -sm "update"; done自证 场景2. 构造10个文件 命令作用for i in {1..10}; do date >> "file_$i.log&quo…

Quiz 7: Files | Python for Everybody 配套练习_解题记录

文章目录 课程简介Quiz 7: Files 单选题&#xff08;1-10&#xff09;编程题Exercise 7.2 课程简介 Python for Everybody 零基础程序设计&#xff08;Python 入门&#xff09; This course aims to teach everyone the basics of programming computers using Python. 本课程…

项目——学生信息管理系统1

目录 创建项目 1. 修改Eclipse的编码为UTF-8,具体参考给的文档 1.1 设置代码自动保存 2. 创建Java项目 分包 添加数据库驱动jar包依赖 复制数据库驱动jar包到lib目录下 添加依赖 创建登陆页面 在 org.xingyun.view 包下创建 LoginFrm 选择 WindowBuilder下的 Swing D…

oracle 重复启动监听程序故障

又是一起 oracle 无法连接问题&#xff0c;检查配置都是正常的。 原来是碰到一个oralce的bugl了。 还真就是这个问题&#xff0c;子进程一kill掉&#xff0c;就恢复了。

微服务实战项目-学成在线-课程发布模块

学成在线-课程发布模块 1 模块需求分析 1.1 模块介绍 课程信息编辑完毕即可发布课程&#xff0c;发布课程相当于一个确认操作&#xff0c;课程发布后学习者在网站可以搜索到课程&#xff0c;然后查看课程的详细信息&#xff0c;进一步选课、支付、在线学习。 下边是课程编辑…

视频解说小程序看点小程序搭建上线,流量主对接实现广告收益

什么是视频解说小程序&#xff1f; 影视剪辑和解说&#xff0c;我们都知道有这类的抖音号&#xff0c;这时候就用到我们小程序了&#xff0c;流量主产生了收益。把视频解说上传到小程序&#xff0c;设置为广告观看&#xff0c;这样引导用户去小程序看&#xff0c;就产生一个广告…