• 组件的自定义事件②


    事件的解绑

    首先声明事件的解绑他不是必须的,但他一定是推荐的。这就跟定时器的关闭一样,我们只要开启就应该选择一个合适的时机关掉,但是你不关,就等着用户关网页,也是可以的。

    我们在上一篇的基础上对事件进行解绑。

    解绑使用的语法:$off(事件名)

    注意:在哪了绑定的,就在哪里解绑

    代码实现如下:

    <template>
        <div class="demo">
            <h2 class="stu" >学生名称:{{name}}</h2>
            <h2 >学生年纪:{{age}}</h2>
            <button @click="studentNameGetter(name)">点击将学生名称交给父组件App</button>
            <button @click="unbind">点击解绑事件</button>
        </div>
    </template>
    
    <script>
    
        export default {
            name:'MyStudent',
            data(){
                return {
                    name:'张三',
                    age:18
                }
            },
            methods:{
                studentNameGetter(name){
                    // 触发Student组件实例身上的stuName事件
                    this.$emit('stuName',name)
                },
                unbind(){
                    this.$off('stuName')
                }
            }
        }
    
    </script>
    
    • 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

    但是如上的方法只能解绑一个自定义事件,如果我们有多个自定义事件需要解绑,则在上面的方法中传入一个数组即可:

    $off(['事件1',‘事件2’,......])

    Tips:
    $off()
    如果什么都不传,则会把这个组件实例身上所有的自定义事件全部解绑

    要点回顾:
    在这里插入图片描述
    在销毁vm执行了$destroy()之后,会关闭所有的监听器,子组件,以及事件监听器。这时原生的DOM事件可以使用,因为他拆掉的是自定义事件的事件监听器。

    两个注意点

    $on()方法中this的指向问题

    App组件

    <template>
        <div>
            <h2 ref="title" >欢迎来到{{n}}</h2>
            <hr>
            <SchoolName :getSchoolName="getSchoolName"></SchoolName>
            <StudentName ref="Student"></StudentName>
    <!--        <StudentName v-on:stuName="getStudentName"></StudentName>-->
    <!--        <StudentName @stuName ="getStudentName"></StudentName>-->
    
        </div>
    </template>
    
    <script>
    
            import SchoolName from "@/components/School";
            import StudentName from "@/components/Student";
            export default {
                components:{
                    SchoolName,
                    StudentName
                },
                data(){
                    return {
                        n:'CSDN'
                    }
                },
                methods:{
                    getSchoolName(name){
                        console.log('App组件已经收到了学校的名字:',name)
                    },
                    getStudentName(name){
                        console.log('App组件已经收到了学生的名字:',name)
                    }
                },
                mounted() {
                        this.$refs.Student.$on('stuName',this.getStudentName)
                }
            }
    </script>
    
    • 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
    • 37
    • 38
    • 39

    在$on()方法中第二个参数我们既然传入的是一个函数,那么我们能不能直接将函数定义在on方法中,而不是在methods中定义呢?

    App组件:

    <script>
    
            import SchoolName from "@/components/School";
            import StudentName from "@/components/Student";
            export default {
                components:{
                    SchoolName,
                    StudentName
                },
                data(){
                    return {
                        n:'CSDN'
                    }
                },
                methods:{
                    getSchoolName(name){
                        console.log('App组件已经收到了学校的名字:',name)
                    },
                    // getStudentName(name){
                    //     console.log('App组件已经收到了学生的名字:',name)
                    // }
                },
                mounted() {
                        this.$refs.Student.$on('stuName',function (name) {
                            console.log(this)
                            console.log('App组件已经收到了学生的名字:',name)
                        })
                }
            }
    </script>
    
    • 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

    在这里插入图片描述

    在这里插入图片描述

    我们发现this的指向并不是App

    注意:谁触发了这个事件,此时$on()方法中this指向就是谁

    这种情况造成的影响就是如果我们想要把从子组件传递过来的数据挂载到当前父组件的身上的时候,会发现挂载不上,因为此时this的指向已经不是这个父组件了

    那么我们怎么解决这个问题呢?两种方法:

    • 像以前一样,中规中矩的把回调方法写在methods中
    • 将$on()方法中传入的回调方法写成箭头函数。因为箭头函数没有自己的this,于是就向外寻找,而mounted()函数中的this已经被维护成了当前组件,也就是App,所以是可行的。

    代码如下:

    <script>
    
            import SchoolName from "@/components/School";
            import StudentName from "@/components/Student";
            export default {
                components:{
                    SchoolName,
                    StudentName
                },
                data(){
                    return {
                        n:'CSDN'
                    }
                },
                methods:{
                    getSchoolName(name){
                        console.log('App组件已经收到了学校的名字:',name)
                    },
                    // getStudentName(name){
                    //     console.log('App组件已经收到了学生的名字:',name)
                    // }
                },
                mounted() {
                        this.$refs.Student.$on('stuName',(name) => {
                            console.log(this)
                            console.log('App组件已经收到了学生的名字:',name)
                        })
                }
            }
    </script>
    
    • 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

    此时的this就是App组件了:
    在这里插入图片描述

    绑定误解

    我们在给组件绑定一些原生的DOM事件的时候,会发现不能被触发,这是因为Vue会把一切在组件上绑定的事件当作自定义事件。

    在这里插入图片描述
    那么我们怎么解决这个问题呢?使用.native事件修饰符即可:
    在这里插入图片描述
    如此这个事件才会被当作原生的DOM事件去解析。

    他的底层是把click事件交给了Student组件的最外层元素。

    Student组件:
    在这里插入图片描述

    也就是这个大的div。

    此处也从侧面印证了一个事实:组件的template里面只能有一个根元素!
    如果有多个的话,此时你的click事件应该给谁呢?(当然这只是其中一个印证方向)

    组件的自定义事件总结

    组件的自定义事件

    1. 一种组件间通信的方式,适用于:子组件 ===> 父组件

    2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。

    3. 绑定自定义事件:

      1. 第一种方式,在父组件中:<Demo @eventName="test"/><Demo v-on:eventName="test"/>

      2. 第二种方式,在父组件中:

        <Demo ref="demo"/>
        ......
        mounted(){
           this.$refs.xxx.$on('eventName',this.test)
        }
        
        • 1
        • 2
        • 3
        • 4
        • 5
      3. 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。

    4. 触发自定义事件:this.$emit('eventName',数据)

    5. 解绑自定义事件this.$off('eventName')

    6. 组件上也可以绑定原生DOM事件,需要使用native修饰符。

    7. 注意:通过this.$refs.xxx.$on('eventName',回调)绑定自定义事件时,回调要么配置在methods中要么用箭头函数,否则this指向会出问题!

  • 相关阅读:
    2022-9-17 第七小组 学习日记 (day72)SSM架构
    代码随想录训练营第56天|583.两个字符串的删除操作,72.编辑距离
    分布式版本控制工具 Git 的使用方式
    安卓TextView的lineHeight*lineCount!=height问题,解决不支持滚动的系统下对多页Text进行分页
    最新Spring 6手写实现Sping IOC保姆级教程
    【MySQL】库和表的操作
    华为云API图像识别Image的趣味性—AI识别迈克尔·杰克逊
    SELinux for Android的基本知识和实战
    jmeter性能测试使用梯度测试的方法
    ACL原理与配置(一、前言 二、ACL概述 三、ACL的组成实验演示通配符(1)通配符(2) ACL的分类与标识ACL基本配置 ACL高级配置​编辑)
  • 原文地址:https://blog.csdn.net/zyb18507175502/article/details/125548647