Vue和React的自定义事件总结 | 青训营笔记

424 阅读3分钟

这是我参与「第五届青训营」笔记创作活动的第7天。今天的JS学习值得记录的点不多,我打算记录一下最近学习React时和之前Vue有所混淆的一个问题。下面总结Vue2、Vue3和React中常用的一个场景对比:通过自定义事件实现父子组件通信。Vue和React的总体思路均为 父组件传给子组件一个回调函数,子组件来触发该函数,以给该函数传参的方式实现 由子组件到父组件的信息传递

一、本堂课重点内容:

Vue2、Vue3和React中常用的一个场景对比:通过自定义事件实现父子组件通信。

二、详细知识点介绍:

Vue2

在Vue2中,常常通过父组件给子组件绑定一个自定义事件,实现子组件给父组件传递数据。这种方式本质上是将在父组件中定义的方法传给子组件让子组件去调用。与React不同的是,Vue将这种自定义事件的情景从props中摘了出来,子组件并不能通过props直接拿到回调函数。

  1. 首先 在父组件内 自定义事件 event 和 用于响应自定义事件 event 的函数方法 funcA。通过 v-on 指令绑定给子组件

    <Child v-on:event="funcA" />
    // v-on 指令可以简写为
    <Child @:event="funcA" />
    
  2. 在子组件中,在合适的场景中触发 父组件的自定义事件,进而调用绑定的函数,从而给函数传参

    • 在HTML中

      <button @click="$emit('event', arg)">
      
    • 在JS中

      this.$emit('atguigu', arg)
      

    核心逻辑就是 利用$emit手动触发自定义事件 event,进而调用绑定在事件上的函数。同时,$emit还可以给绑定的函数传参。

Vue3

vue3相比vue2,自定义事件复杂了很多。具体流程如下。

  1. 首先 在子组件内 自定义事件 event。规范起见,用大写常量 EMIT_EVENT 代替。常量经常写在不带setup的srcipt标签里。

    <script>
        const EMIT_EVENT = 'event';
    </script>
    <script setup>
        ...
    </script>
    
  2. 然后 在父组件内定义 用于响应子组件的自定义事件 event 的函数方法funcA 。接着就可以在父组件中使用以下方式来完成对子组件事件的响应:

    <Child @event="funcA"/> 
    或者
    <Child v-on:event="funcA" />
    
  3. 然后 在子组件内注册自定义事件 event。Vue3中使用 defineEmits() 函数

    <script setup>
        defineEmits('event');
        // 如果已经定义常量 EMIT_EVENT 来代替 event
        defineEmits(EMIT_EVENT);
    </script>
    
  4. 最后,在子组件内以需要的方式去触发自定义事件,并给 funcA 传参:

    • 在HTML中,使用:$emit('event', arg);

      1.png

      或者在 const EMIT_EVENT = 'event'; 的基础下使用 $emit(EMIT_EVENT, arg)

    • 在JS中,则需要在

      const emits = defineEmits('event');
      const emits = defineEmits(EMIT_EVENT);
      

      的前提下使用:emits('event', arg);

      或者在 const EMIT_EVENT = 'event'; 的基础下使用 emits(EMIT_EVENT, arg)

      2.png

Vue3 里面最好的例子就是项目中的常常自己封装的m-button组件。

React

react 可以说是最为直接的体现了 父组件传给子组件一个回调函数,子组件来触发该函数,以给该函数传参的方式实现 由子组件到父组件的信息传递 这样的思路。无论是类式组件还是函数式组件,都是利用子组件的props完成父子组件之间的通信。

  1. 首先 在父组件内 自定义函数 funcA。在函数 funcA 中,改变了父组件的state中的某些数据。

    export default class Father extends Component{
        state = {...}
        funcA = (dataFromChild) => {
            ...
            this.setState({/*利用dataFromChild更新父组件的state*/})
        }
    }
    
  2. 然后 在父组件的 JSX 中使用到子组件的部分,以 props 的形式传递给子组件

    render() {
        return (
            <div>
                <Child funcToChild={this.funcA} />
            </div>
        );
    }
    
  3. 在子组件中,接收出props(类式组件是 this.props,函数式组件则是从函数参数中接收到的 props),然后利用 this.props.funcToChild 在合适的地方调用函数即可。在子组件中构造好数据,以参数形式传递给函数 this.props.funcToChild ,就相当于调用了定义在父组件中的方法 funcA ,实现了在子组件中更改父组件的数据的效果。

三、实践练习例子:

例子已经在文章中举出。

四、课后个人总结:

本章的知识点需要大量的实例和参考资料来辅助理解。

五、引用参考:

我主要是基于老师讲解提供的代码仓库进行理解和分析,并记录了自己的心得。