zl程序教程

您现在的位置是:首页 >  前端

当前栏目

Vue 中自定义事件

Vue事件 自定义
2023-09-27 14:21:38 时间

Vue 中自定义事件

1:自定义说明

/*
组件的自定义事件
一种组件间通信的方式,适用于:子组件 ===> 父组件

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

绑定自定义事件:

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

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

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

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

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

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

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




**/





2:界面效果图

image

image

3:代码结构

image



3:代码示例

vue.config.js


const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  lintOnSave:false /*关闭语法检查*/
})



main.js

 //引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue生产提示
Vue.config.productionTip=false;

// 创建Vm
const vm = new Vue(  {
        el:'#app',
        render: (h) => h(App)
   });


App.vue


<template>
  <div>
    <hr/>
    <div class="divCss">
        <h1 class="h1Css">Vue中的组件的自定义事件</h1>
        <hr/>
        <!-- 调用组件,传递数据 -->
        <School :getSchoolName="getSchoolName"/> <!-- :getSchoolName="getSchoolName" :==>通过父组件给子组件传递函数类型的props实现:子给父传递数据    -->
        <hr/>
        <!--通过父组件给子组件绑定一个自定义事件实现:子给父传递数据 (第一种写法:使用@或者v-on)-->
        <Student v-on:getDataByStudent.once="getStudentName" />
        <!-- v-on:getDataByStudent="getStudentName"  给哪个子组件绑定事件,就找哪个子组件获取点击事件的v-on触发事件
             v-on:getDataByStudent.once  控制按钮点击事件只有1次有效
        -->
        <hr/>
        <!--通过父组件给子组件绑定一个自定义事件实现:子给父传递数据 (第二种写法:使用ref)-->
        <StudentTom ref="studentTom" @click.native="show" /><!-- 写入方法:studentTom   获取方法(挂载在 mounted()方法里):this.$refs.studentTom -->
        <hr/>
        <h1>接收子组件传递过来的数据信息进行展示操作:---》 学生信息是:{{studentTomName}}</h1>
    </div>

  </div>
</template>
<script>

    import School from './components/School.vue';
    import Student from './components/Student.vue';
    import StudentTom from './components/StudentTom.vue';


    export default {
        name:'App',
        data(){
          return{
            studentTomName:''
          }
        },
        components:{
            Student,
            School,
            StudentTom
        },
        methods:{
          getSchoolName(name){
              console.log('App收到里学校名:',name);
          },
          getStudentName(name,...params){
            console.log('App收到里学生名:',name,JSON.parse(params));
          },
          /**
           * ...params  形参对象 []
           */
          getStudentTomName(name,...params){
            console.log('App收到里学生名:',name,params);
            this.studentTomName=name;
          },
          getStudentTomAge(age,...params){
            console.log('App收到里学生年龄:',age,params);
          },
          show(){
            console.log("展示App绑定原生态点击事件:@click.native='show' ");
          }
        },
        mounted () {
          //  时间回调事件:3秒钟后再进行回调===》使用方式比较灵活
          setTimeout(()=>{
              /**
               * 挂载方法:getDataByStudentTom
               * 挂载方法回调方法:getStudentName
               */
              this.$refs.studentTom.$on('getDataByStudentTom',this.getStudentTomName); //绑定自定义事件
              //绑定自定义事件
             /*
             this.$refs.studentTom.$on('getDataByStudentTom',(name,...params)=>{
                console.log('App收到里学生名:',name,params);
                this.studentTomName=name;  //说明:此处的this 是父组件的this对象
              });
             */
             /*
              this.$refs.studentTom.$on('getDataByStudentTom',function(name,...params){
                console.log('App收到里学生名:',name,params);
                this.studentTomName=name;  //说明:此处的this 是子组件的this对象
              });
              */

              this.$refs.studentTom.$on('getStudentTomAge',this.getStudentTomAge); //绑定自定义事件
              // this.$refs.studentTom.$once('getDataByStudentTom',this.getStudentTomName); //绑定自定义事件(一次性)
          },3000);
        }
    }
</script>
<!--
  1指定Css 样式的编写方式
  less 最大特点内容可以嵌套着写

 -->
<style lang="less">
   .divCss{
        background-color: chocolate;
        margin: auto;
        padding: 20px;

        .h1Css{
        font-size: 36px;
        color: white;
   }
   }

</style>


School.vue

<!--
  ## scoped样式

  1. 作用:让样式在局部生效,防止冲突。
  2. 写法:```<style scoped>```
 -->
<template>
    <div  class="ClassStyle">
      <h1  style="color:red">{{msg}}</h1>
      <h2>学校名称:{{name }}</h2>
      <h2>学校地址:{{address}}</h2>
      <button  @click="sendSchoolNameToApp">把学校名字给App</button>
    </div>
</template>
  <script>
      export default {
        name:'School',
        data () {
          return {
            msg:'学校信息',
            name:'华南师范大学',
            address:'广州市天河区中山大道西55号'
          }
        },
        props:['getSchoolName'],
        methods: {
          sendSchoolNameToApp(){
            this.getSchoolName(this.name);
          }
        }

      }
  </script>
<!--scoped 控制组件的Css样式为局部样式不会为同名的cs样式名的冲突导致样式覆盖  -->
  <style  scoped>
    .ClassStyle{
      background-color: aquamarine;
      padding: 5px;
    }
  </style>


Student.vue

<!--
 ## scoped样式

1. 作用:让样式在局部生效,防止冲突。
2. 写法:```<style scoped>```
 -->
<template>
    <div  class="ClassStyle">
      <h1  style="color:red">{{msg}}</h1>
      <h2>学生名称:{{name}}</h2>
      <h2>学生性别:{{sex}}</h2>
      <button @click="sendStudentNameToApp" >把学生名字给App</button>
      <button @click="death" >销毁当前Student组件的实例(vc)对象</button>
      <hr />
      <h2>当前求和为:{{score}}</h2>
      <button @click="scoreAdd">点击进行求和操作</button>
      <br/>
    </div>
</template>
  <script>
      export default {
        name:'Student',
        data () {
          return {
            msg:'学生信息:One',
            name:'向北',
            sex:'男',
            score:12
          }
        },
        methods: {
          sendStudentNameToApp(){
            // 从App获取的getDataByStudent方法,并触发getDataByStudent事件
            let params=['999','666','7777','555','4444'];
            this.$emit('getDataByStudent',this.name,JSON.stringify(params));
          },
          death(){
            console.log('开始销毁当前student组件实例......');
            this.$destroy();//销毁了当前student组件的实例 销毁后所有的student的自定义事件全部不奏效
            console.log('结束销毁当前student组件实例......');

          },
          scoreAdd(){
            console.log("add回调被调用了......");
            this.score ++ ;
            console.log("add回调结束......:当前值为:",this.score);
          }
        }

      }
  </script>
 <!--scoped 控制组件的Css样式为局部样式不会为同名的cs样式名的冲突导致样式覆盖  -->
 <style  scoped>
    .ClassStyle{
      background-color:lightskyblue;
      padding: 5px;
    }
  </style>


StudentTom.vue

<!--
 ## scoped样式

1. 作用:让样式在局部生效,防止冲突。
2. 写法:```<style scoped>```
 -->
 <template>
  <div  class="ClassStyle">
    <h1  style="color:red">{{msg}}</h1>
    <h2>学生名称:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <h2>学生年龄:{{age}}</h2>
    <button @click="sendStudentNameToApp" >把学生名字给App</button><br/>
    <button @click="sendStudentAgeToApp" >把学生年龄给App</button><br/>
    <button @click="unbindToOnce">解绑一个自定义绑定事件</button><br/>
    <button @click="unbindMore">解绑多个自定义绑定事件</button><br/>
    <br/>
  </div>
</template>
<script>
    export default {
      name:'StudentTom',
      data () {
        return {
          msg:'学生信息:Two',
          name:'Tom',
          sex:'男',
          age:20
        }
      },
      methods: {
        sendStudentNameToApp(){
          // 从App获取的getDataByStudent方法,并触发getDataByStudent事件
          this.$emit('getDataByStudentTom',this.name,999,666,7777,555,4444);

        },
        sendStudentAgeToApp(){
          // 从App获取的getDataByStudent方法,并触发getDataByStudent事件
          this.$emit('getStudentTomAge',this.age);
        },
        unbindToOnce(){
          console.log('开始解绑StudentTom里事件......:getDataByStudentTom');
          this.$off('getDataByStudentTom');
          console.log('结束解绑StudentTom里事件......:getDataByStudentTom该事件点击效果失效。');
        },
        unbindMore(){
          console.log('开始解绑StudentTom里所有事件.....');
          let unbindMothods=['getDataByStudentTom','getStudentTomAge'];
          this.$off(unbindMothods);
          // this.$off();//解绑所有的自定义绑定事件
          console.log('结束解绑StudentTom里所有事件......');
        }
      }


    }
</script>
<!--scoped 控制组件的Css样式为局部样式不会为同名的cs样式名的冲突导致样式覆盖  -->
<style  scoped>
  .ClassStyle{
    background-color:lightskyblue;
    padding: 5px;
  }
</style>