vue3的组件事件和defineEmits

文章目录

    • 1. 事件基础
      • 示例
        • Blog.vue
        • BlogPost.vue
    • 2. 触发与监听事件
      • 2.1 触发事件
      • 2.2 监听事件
    • 3. 事件参数
      • 3.1 示例1
        • Blog.vue
        • BlogPost.vue
      • 3.2 示例2(defineEmits)
        • MyComponent.vue
        • Test.vue
    • 4. 声明触发的事件
    • 5. 事件校验
      • 示例1
        • Blog.vue
        • BlogPost.vue
      • 示例2(defineEmits)
        • MyComponent.vue
        • Test.vue

1. 事件基础

  • 子组件有时候需要与父组件进行交互,子组件需要通知父组件做一些事(比如:prop是单向数据量,子组件不应该直接修改prop绑定的值,而是应该抛出一个事件来通知父组件做出改变
  • 为了解决这个问题,组件实例提供了一个自定义事件系统,父组件可以通过v-on@ 来选择性地监听子组件上抛的事件,就像监听原生 DOM 事件那样,当监听到子组件上抛出的事件时,就会执行对应事件绑定的监听函数
    • 子组件可以通过调用内置的 $emit 方法,通过传入事件名称来抛出一个事件
    • 子组件使用内置的 $emit 方法中,可以使用 $event作为事件参数
    • 我们可以通过 emits 选项来声明需要抛出的事件(emits声明选项不是必须的)
      • 这声明了一个组件可能触发的所有事件,还可以对事件的参数进行验证
      • 还可以让 Vue 避免将它们作为原生事件监听器隐式地应用于子组件的根元素。
        • 如果子组件中声明了emits:[‘click’]选项,然后在某个按钮下使用了$emit(‘click’)去触发click事件,则父组件中使用该子组件时,使用@click=‘handleClick’去监听click事件时,不会认为这是原生dom的点击事件,只有当子组件使用$emit(‘click’)触发click事件时,才会触发hanleClick函数。如果不加emits:[‘click’]选项,则只要点击就会触发handleClick事件。

示例

vue3的组件事件和defineEmits_第1张图片

Blog.vue
<template>
    <div :style="{ fontSize: postFontSize + 'em' }">
        <BlogPost 
            v-for="post in posts" 
            :key="post.id" 
            :title="post.title"
            @enlarge-text="postFontSize += 0.1"/>
    div>
template>

<script >
import BlogPost from './BlogPost.vue'
export default {
    name: 'Blog',
    components: {
        BlogPost
    },
    data() {
        return {
            posts: [
                { id: 1, title: 'My journey with Vue' },
                { id: 2, title: 'Blogging with Vue' },
                { id: 3, title: 'Why Vue is so fun' }
            ],
            postFontSize: 1
        }
    }
}

script>

<style lang="scss">style>
BlogPost.vue
<template>

    <div class="blog-post">
        <h4>{{ title }}h4>
        <button @click="$emit('enlarge-text')">Enlarge textbutton>
    div>

template>

<script>

export default {
    name: 'BlogPost',
    props: ['title'],
    // 这个emits声明选项不是必须的
    emits: ['enlarge-text']
}

script>

<style lang="scss">style>

2. 触发与监听事件

2.1 触发事件

  • 在组件的模板表达式中,可以直接使用 $emit 方法触发自定义事件

  • $emit() 方法在组件实例上也同样以 this.$emit() 的形式可用:

    <templte>
    	<button @click="$emit('someEvent')">click mebutton>
    template>
    
    <script>
    	export default {
    	  methods: {
    	    submit() {
    	      this.$emit('someEvent')
    	    }
    	  }
    	}
    script>
    

2.2 监听事件

  • 父组件可以通过 v-on (缩写为 @) 来监听事件

  • 组件的事件监听器也支持 .once 修饰符
    - 触发事件时建议使用camelCase 形式(驼峰命名,首字母小写),父组件监听是可以使用kebab-case 形式(短横线分隔,推荐)

  • 组件触发的事件没有冒泡机制,你只能监听直接子组件触发的事件

    • 平级组件或是跨越多层嵌套的组件间通信,应使用一个外部的事件总线
    • 或者使用一个全局状态管理方案
    <MyComponent @some-event="callback" />
    
    <MyComponent @some-event.once="callback" />
    

3. 事件参数

  • 有时候会需要在触发事件时附带一个特定的值(事件参数)
  • 可以写一个内联的箭头函数作为监听器,此函数会接收到事件附带的参数
  • 也可以用一个组件方法来作为事件处理函数,该方法也会接收到事件所传递的参数
  • 所有传入 $emit() 的额外参数都会被直接传向监听器。
    • 举例来说,$emit(‘foo’, 1, 2, 3) 触发后,监听器函数将会收到这三个参数值。

3.1 示例1

vue3的组件事件和defineEmits_第2张图片

Blog.vue
<template>
    {{ count }}
    <BlogPost @increase-by="(n) => count += n" />
    <BlogPost @increase-by="increaseCount" />
template>

<script >
import BlogPost from './BlogPost.vue'
export default {
    name: 'Blog',
    components: {
        BlogPost
    },
    data() {
        return {
            count: 0
        }
    },
    methods: {
        increaseCount(n,m,e) {
            console.log(n,m,e); // 1, 2, PointerEvent {isTrusted: true, _vts: 1682821628803, pointerId: 1, width: 1, height: 1, …}
            this.count += n
        }
    }
}

script>

<style lang="scss">style>
BlogPost.vue
<template>

    <div class="blog-post">
        <button @click="$emit('increaseBy', 1, 2, $event)">
            Increase by 1
        button>
    div>

template>

<script>

export default {
    name: 'BlogPost',
}

script>

<style lang="scss">style>

3.2 示例2(defineEmits)

  • 子组件可以触发自定义事件,
  • 父组件使用该子组件时,可以监听该组件的事件,并为监听的事件绑定事件处理函数,
    • 当该子组件触发了该事件时,父组件对应的事件处理函数就会执行。

vue3的组件事件和defineEmits_第3张图片

MyComponent.vue
<template>

    
    
    
    
    
    <button v-on:click="$emit('doUpdate',$event,1,2)">触发doUpdate事件button> <br/>

    <button v-on:click="$emit('refresh', {name:'zzhua',age:Math.floor(Math.random() * 20)})">触发refresh事件button>
    子组件中person: {{ person }}<br/>

    
    <button v-on:click.once="handleClick()">触发click事件button>
    
template>

<script lang="ts" setup>

    import { ref,reactive,onUpdated } from 'vue'

    /* 1. defineEmits() 宏不能在子函数中使用。它必须直接放置在 
                    
                    

你可能感兴趣的:(#,vue学习,javascript,vue.js,前端)