• react之响应事件


    第二章 - 添加交互

    界面上的控件会根据用户的输入而更新。例如,点击按钮切换轮播图的展示。在 React 中,随时间变化的数据被称为状态(state)。你可以向任何组件添加状态,并按需进行更新。在本章节中,你将学习如何编写处理交互的组件,更新它们的状态,并根据时间变化显示不同的效果。

    响应事件

    React允许你向JSX中添加事件处理程序。事件处理程序是你自己的函数,它将在用户交互时被触发,如点击,悬停,焦点在表单输入框上等等。

    ); } function Button({ onClick, children }) { return ( ); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    添加事件处理函数

    如需添加一个事件处理函数,你需要先定义一个函数,然后将其作为prop传入合适的 JSX 标签。例如,这里有一个没有绑定任何事件的按钮:

    export default function Button() {
      return (
        
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    按照如下三个步骤,即可让它在用户点击时显示消息:

    1. Button 组件 内部 声明一个名为 handleClick 的函数。
    2. 实现函数内部的逻辑(使用 alert 来显示消息)。
    3. 添加 onClick={handleClick}
    export default function Button() {
      function handleClick() {
        alert('你点击了我!');
      }
    
      return (
        
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    你可以定义 handleClick 函数然后作为prop传入 button。其中 handleClick是一个事件处理函数。事件处理函数有如下特点:

    • 通常在你的组件 内部 定义。
    • 名称以 handle 开头,后跟事件名称
    • 按照惯例,通常将事件处理程序命名为 handle,后接事件名。你会经常看到 onClick={handleClick}onMouseEnter={handleMouseEnter} 等。

    或者,你也可以在JSX中定义一个内联的事件处理函数:

    或者,直接使用更为简洁的箭头函数:

    以上所有方式都是等效的。当函数体较短时,内联事件处理函数会很方便。

    陷进

    传递给事件处理函数的函数应直接传递,而非调用。例如:

    传递一个函数(正确)调用一个函数(错误)

    区别很微妙。在第一个示例中,handleClick 函数作为 onClick 事件处理函数传递。这会让 React 记住它,并且只在用户点击按钮时调用你的函数。

    在第二个示例中,handleClick() 中最后的 () 会在 渲染 过程中 立即 触发函数,即使没有任何点击。这是因为在 JSX {} 之间的 JavaScript 会立即执行。

    当你编写内联代码时,同样的陷阱可能会以不同的方式出现:

    传递一个函数(正确)调用一个函数(错误)

    如果按如下方式传递内联代码,并不会在点击时触发,而是会在每次组件渲染时触发:

    // 这个 alert 在组件渲染时触发,而不是点击时触发!
    
    

    如果你想要定义内联事件处理函数,请将其包装在匿名函数中,如下所示:

    这里创建了一个稍后调用的函数,而不会在每次渲染时执行其内部代码。

    在这两种情况下,你都应该传递一个函数:

    在事件处理函数中读取 props

    由于事件处理函数声明于组件内部,因此它们可以直接访问组件的props。示例中的按钮,当点击时会弹出带有message prop的alert:

    function AlertButton({ message, children }) {
      return (
        
      );
    }
    
    export default function Toolbar() {
      return (
        
    播放电影 上传图片
    ); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    此处有两个按钮,会展示不同的消息。你可以尝试更改传递给它们的消息。

    将事件处理函数作为props传递

    通常,我们会在父组件中定义子组件的事件处理函数。比如:置于不同位置的 button 组件,可能最终执行的功能不同 – 也许时播放电影,也许是上传图片。

    为此,将组件从父组件接接收的prop作为事件处理函数传递,如下所示:

    function Button({ onClick, children }) {
      return (
        
      );
    }
    
    function PlayButton({ movieName }) {
      function handlePlayClick() {
        alert(`正在播放 ${movieName}!`);
      }
    
      return (
        
      );
    }
    
    function UploadButton() {
      return (
        
      );
    }
    
    export default function Toolbar() {
      return (
        
    ); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    示例中,Toolbar 组件渲染了一个 PlayButton 组件和 UploadButton 组件:

    • PlayButtonhandlePlayClick 作为 onClick prop 传入 Button 组件内部。
    • UploadButton() => alert('正在上传!') 作为 onClick prop 传入 Button 组件内部。

    最后,你的 Button 组件接收一个名为 onClick 的 prop。它直接将这个 prop 以 onClick={onClick} 方式传递给浏览器内置的 ); } export default function App() { return (

    ); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    上述示例中,

    ); } function Button({ onClick, children }) { return ( ); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    请注意,App 组件并不需要知道 Toolbar 将会对 onPlayMovieonUploadImage什么 。上述示例是 Toolbar 的实现细节。其中,Toolbar 将它们作为 onClick 处理函数传递给了 Button 组件,其实还可以通过键盘快捷键来触发它们。根据应用程序特定的交互方式(如 onPlayMovie)来命名 prop ,可以让你灵活地更改以后使用它们的方式.

    事件传播

    事件处理函数还将捕获任何来自子组件的事件。通常,我们会说事件会沿着树向上“冒泡”或“传播”:它从事件发生的地方开始,然后沿着树向上传播。

    下面这个

    包含两个按钮。
    和每个按钮都有自己的 onClick 处理函数。你认为点击按钮时会触发哪些处理函数?

    export default function Toolbar() {
      return (
        
    { alert('你点击了 toolbar !'); }}>
    ); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    如果你点击任一按钮,它自身的 onClick 将首先执行,然后父级

    onClick 会接着执行。因此会出现两条消息。如果你点击 toolbar 本身,将只有父级
    onClick 会执行

    陷阱

    在react中所有事件都会传播,除了onScroll,它仅适用于你附加到的JSX标签。

    阻止传播

    事件处理函数接收一个 事件对象 作为唯一的参数。按照惯例,它通常被称为 e ,代表 “event”(事件)。你可以使用此对象来读取有关事件的信息。

    这个事件对象还允许你阻止传播。如果你想阻止一个事件到达父组件,你需要像下面 Button 组件那样调用 e.stopPropagation()

    function Button({ onClick, children }) {
      return (
        
      );
    }
    
    export default function Toolbar() {
      return (
        
    { alert('你点击了 toolbar !'); }}>
    ); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    当你点击按钮时:

    1. React 调用了传递给
    2. 定义在 button 中的处理函数执行了如下操作:
      • 调用 e.stopPropagation(),阻止事件进一步冒泡。
      • 调用 onClick 函数,它是从 Toolbar 组件传递过来的 prop。
    3. Toolbar 组件中定义的函数,显示按钮对应的 alert。
    4. 由于传播被阻止,父级
      onClick 处理函数不会执行。

    由于调用了 e.stopPropagation(),点击按钮现在将只显示一个 alert(来自 ); }

    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    你也可以在调用父元素 onClick 函数之前,向这个处理函数添加更多代码。此模式是事件传播的另一种 替代方案 。它让子组件处理事件,同时也让父组件指定一些额外的行为。与事件传播不同,它并非自动。但使用这种模式的好处是你可以清楚地追踪因某个事件的触发而执行的整条代码链。

    如果你依赖于事件传播,而且很难追踪哪些处理程序在执行,及其执行的原因,可以尝试这种方法。

    阻止默认行为

    某些浏览器事件具有与事件相关联的默认行为。例如,点击

    表单内部的按钮会触发表单提交事件,默认情况下将重新加载整个页面:

    export default function Signup() {
      return (
         alert('提交表单!')}>
          
          
        
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    你可以调用事件对象中的 e.preventDefault() 来阻止这种情况发生:

    export default function Signup() {
      return (
        
    { e.preventDefault(); alert('提交表单!'); }}>
    ); }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    不要混淆 e.stopPropagation()e.preventDefault()。它们都很有用,但二者并不相关:

    事件处理函数可以包含副作用吗?

    当然可以!事件处理函数是执行副作用的最佳位置。

    与渲染函数不同,事件处理函数不需要是 纯函数,因此它是用来 更改 某些值的绝佳位置。例如,更改输入框的值以响应键入,或者更改列表以响应按钮的触发。但是,为了更改某些信息,你首先需要某种方式存储它。在 React 中,这是通过 state(组件的记忆) 来完成的。

    摘要

    • 你可以通过将函数作为 prop 传递给元素如
    • 必须传递事件处理函数,而非函数调用! onClick={handleClick} ,不是 onClick={handleClick()}
    • 你可以单独或者内联定义事件处理函数。
    • 事件处理函数在组件内部定义,所以它们可以访问 props。
    • 你可以在父组件中定义一个事件处理函数,并将其作为 prop 传递给子组件。
    • 你可以根据特定于应用程序的名称定义事件处理函数的 prop。
    • 事件会向上传播。通过事件的第一个参数调用 e.stopPropagation() 来防止这种情况。
    • 事件可能具有不需要的浏览器默认行为。调用 e.preventDefault() 来阻止这种情况。
    • 从子组件显式调用事件处理函数 prop 是事件传播的另一种优秀替代方案。
  • 相关阅读:
    简述 HTML 的语义化标签是什么?
    大数据安全 | 【实验】仿射加密
    springboot学校快递站点管理系统的设计与实现毕业设计源码111544
    中职组网络安全C模块全漏洞脚本讲解包含4个漏洞的脚本
    深度学习 二:COVID 19 Cases Prediction (Regression)
    任务及任务切换
    4.go语言复合类型简述
    vue模板语法上集
    tcp、http、rpc和grpc得一些个人总结
    Uniswap V2 — 从代码解释 DeFi 协议
  • 原文地址:https://blog.csdn.net/weixin_73918953/article/details/138153674