[Vue]组件自定义事件(二)

简介: [Vue]组件自定义事件(二)

2.4 触发自定义事件向处理函数传递多个参数

在接收参数时,不想书写多个形参,可以使用...扩展运算符将多个参数进行接收。

App.vue

<template>
  <div class="app">
    <h1>{{msg}}</h1>
    <School :getSchoolName="getSchoolName"></School>
    <!-- 
      1. 为子组件绑定自定义事件 MyEvent
          当自定义事件 MyEvent 被触发时,
          会调用事件的处理函数 getStudentName
    -->
    <!-- <Student @MyEvent="getStudentName"></Student> -->
    <!-- 
      2. 使用 ref 进行自定义事件的绑定
    -->
    <Student ref="student"></Student>
  </div>
</template>
<script>
//导入子组件
import Student from './components/Student'
import School from './components/School'
export default {
  name: 'App',
  components: { School, Student },
  data() {
    return {
      msg: '你好啊!'
    }
  },
  methods: {
    getSchoolName(name) {
      console.log('App收到了学校名:', name)
    },
    getStudentName(name, ...params) {
      console.log('App收到了学生名:', name)
      console.log('其他参数:', params)
    }
  },
  mounted() {
    // 为子组件 Student 绑定自定义事件
    this.$refs.student.$on('MyEvent', this.getStudentName)
  }
}
</script>
<style scoped>
.app {
  background-color: gray;
  padding: 5px;
}
</style>

Student.vue

<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">把学生姓名给App</button>
  </div>
</template>
<script>
  export default {
    name:'Student',
    data() {
      return {
        name:'张三',
        sex:'男'
      }
    },
    methods: {
      sendStudentName() {
        console.log('点击了按钮"把学生姓名给App"')
        // 触发自定义事件
        // 将学生姓名传递给自定义事件的处理函数
        // 传递多个参数
        this.$emit('MyEvent', this.name, 1, 2, 3)
      }
    },
  }
</script>
<style scoped>
  .student{
    background-color: pink;
    padding: 5px;
    margin-top: 30px;
  }
</style>

2.5 自定义事件只触发一次

实现方法与使用vue的内置事件一样,使用事件修饰符

App.vue

<template>
  <div class="app">
    <h1>{{msg}}</h1>
    <School :getSchoolName="getSchoolName"></School>
    <Student @MyEvent.once="getStudentName"></Student>
    <!-- <Student ref="student"></Student> -->
  </div>
</template>
<script>
//导入子组件
import Student from './components/Student'
import School from './components/School'
export default {
  name: 'App',
  components: { School, Student },
  data() {
    return {
      msg: '你好啊!'
    }
  },
  methods: {
    getSchoolName(name) {
      console.log('App收到了学校名:', name)
    },
    getStudentName(name, ...params) {
      console.log('App收到了学生名:', name)
      console.log('其他参数:', params)
    }
  },
  mounted() {
    // 为子组件 Student 绑定自定义事件
    // 自定义事件只被触发一次
    // this.$refs.student.$once('MyEvent', this.getStudentName)
  }
}
</script>
<style scoped>
.app {
  background-color: gray;
  padding: 5px;
}
</style>

2.6 解绑自定义事件

解绑自定义事件,需要在被绑定自定义事件的子组件实例对象上进行自定义事件的解绑。

2.6.1 语法

解绑自定义事件,调用被绑定自定义事件的子组件实例对象上的$off()方法。

this.$off(自定义事件)

2.6.2 解绑一个自定义事件

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

Student.vue

<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">把学生姓名给App</button>
    <button @click="offEvent">点击解绑自定义事件</button>
  </div>
</template>
<script>
  export default {
    name:'Student',
    data() {
      return {
        name:'张三',
        sex:'男'
      }
    },
    methods: {
      sendStudentName() {
        console.log('点击了按钮"把学生姓名给App"')
        this.$emit('MyEvent', this.name)
      },
      offEvent() {
        // 解绑 MyEvent 自定义事件
        console.log('解绑 MyEvent 自定义事件')
        this.$off('MyEvent')
      }
    },
  }
</script>
<style scoped>
  .student{
    background-color: pink;
    padding: 5px;
    margin-top: 30px;
  }
</style>

2.6.3 解绑多个自定义事件

解绑多个自定义事件,需要向$off()方法中传入一个数组,数组中的元素为需要解绑的自定义事件的名

// 解绑 MyEvent demo 自定义事件
this.$off(['MyEvent', 'demo'])

App.vue

<template>
  <div class="app">
    <h1>{{msg}}</h1>
    <School :getSchoolName="getSchoolName"></School>
    <Student 
      @MyEvent="getStudentName"
      @demo="demo"
    ></Student>
  </div>
</template>
<script>
//导入子组件
import Student from './components/Student'
import School from './components/School'
export default {
  name: 'App',
  components: { School, Student },
  data() {
    return {
      msg: '你好啊!'
    }
  },
  methods: {
    getSchoolName(name) {
      console.log('App收到了学校名:', name)
    },
    getStudentName(name) {
      console.log('App收到了学生名:', name)
    },
    demo() {
      console.log('自定义事件 demo 被触发...')
    }
  },
}
</script>
<style scoped>
.app {
  background-color: gray;
  padding: 5px;
}
</style>

Student.vue

<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">把学生姓名给App</button>
    <button @click="offEvent">点击解绑自定义事件</button>
  </div>
</template>
<script>
  export default {
    name:'Student',
    data() {
      return {
        name:'张三',
        sex:'男'
      }
    },
    methods: {
      sendStudentName() {
        console.log('触发事件:')
        this.$emit('MyEvent', this.name)
        this.$emit('demo')
      },
      offEvent() {
        // 解绑 MyEvent demo 自定义事件
        console.log('解绑 MyEvent demo 自定义事件')
        this.$off(['MyEvent', 'demo'])
      }
    },
  }
</script>
<style scoped>
  .student{
    background-color: pink;
    padding: 5px;
    margin-top: 30px;
  }
</style>

2.6.4 解绑所有自定义事件

解绑所有自定义事件,向$off()方法中不传入参数即可

// 解绑所有自定义事件
this.$off()

Student.vue

<template>
  <div class="student">
    <h2>学生姓名:{{name}}</h2>
    <h2>学生性别:{{sex}}</h2>
    <button @click="sendStudentName">把学生姓名给App</button>
    <button @click="offEvent">点击解绑自定义事件</button>
  </div>
</template>
<script>
  export default {
    name:'Student',
    data() {
      return {
        name:'张三',
        sex:'男'
      }
    },
    methods: {
      sendStudentName() {
        console.log('触发事件:')
        this.$emit('MyEvent', this.name)
        this.$emit('demo')
      },
      offEvent() {
        // 解绑 所有 自定义事件
        console.log('解绑 所有 自定义事件')
        this.$off()
      }
    },
  }
</script>
<style scoped>
  .student{
    background-color: pink;
    padding: 5px;
    margin-top: 30px;
  }
</style>

3. 自定义事件的注意点

3.1 使用 ref 绑定自定义事件中的 this

<template>
  <div class="app">
    <h1>{{msg}} 学生姓名:{{stuName}}</h1>
    <School :getSchoolName="getSchoolName"></School>
    <!-- <Student @MyEvent="getStudentName"></Student> -->
    <Student ref="stu"></Student>
  </div>
</template>
<script>
//导入子组件
import Student from './components/Student'
import School from './components/School'
export default {
  name: 'App',
  components: { School, Student },
  data() {
    return {
      msg: '你好啊!',
      stuName: ''
    }
  },
  methods: {
    getSchoolName(name) {
      console.log('App收到了学校名:', name)
    },
    getStudentName(name) {
      console.log('App收到了学生名:', name)
    },
  },
  mounted() {
    // 由于vue规定
    // 谁触发事件,对应的回调函数中的this就指向谁
    // 由于触发自定义事件 MyEvent 为Student组件,且普通函数拥有自己的this
    // 所以 this 指向 Student组件实例对象
    // this.stuName = name 所以相当于向Student组件中的stuName赋值
    this.$refs.stu.$on('MyEvent', function(name) {
      console.log('App收到了学生名:', name)
      this.stuName = name
    })
  },
}
</script>
<style scoped>
.app {
  background-color: gray;
  padding: 5px;
}
</style>

mounted() {
    // 由于vue规定
    // 谁触发事件,对应的回调函数中的this就指向谁
    // 更改为箭头函数
    // 由于箭头函数没有自己的this
    // 所以会在函数声明位置向外查找,即App组件实例对象
    // 所以箭头函数 this.stuName = name 就是向 App组件实例对象中的stuName赋值
    this.$refs.stu.$on('MyEvent', (name) => {
      console.log('App收到了学生名:', name)
      this.stuName = name
    })
  },

<template>
  <div class="app">
    <h1>{{msg}} 学生姓名:{{stuName}}</h1>
    <School :getSchoolName="getSchoolName"></School>
    <!-- <Student @MyEvent="getStudentName"></Student> -->
    <Student ref="stu"></Student>
  </div>
</template>
<script>
//导入子组件
import Student from './components/Student'
import School from './components/School'
export default {
  name: 'App',
  components: { School, Student },
  data() {
    return {
      msg: '你好啊!',
      stuName: ''
    }
  },
  methods: {
    getSchoolName(name) {
      console.log('App收到了学校名:', name)
    },
    getStudentName(name) {
      console.log('App收到了学生名:', name)
      this.stuName = name
    },
  },
  mounted() {
    // 此种写法,会先将getStudentName函数中的this指向Student组件实例对象
    // 但是由于getStudentName函数声明在App组件的methods中
    // 在methods中的方法,this一定指向所在组件的实例对象
    // 所以getStudentName中的this最终指向App组件实例对象
    this.$refs.stu.$on('MyEvent', this.getStudentName)
  },
}
</script>
<style scoped>
.app {
  background-color: gray;
  padding: 5px;
}
</style>

3.2 为子组件绑定内置事件

<!-- 这样子绑定内置事件,会被认为是自定义事件,只不过自定义事件名字是click -->
<Student ref="stu" @click="show"></Student>
• 1
• 2
// App组件 methods
    show() {
      alert(11111)
    }

为子组件绑定内置事件,且不让内置事件被认为是自定义事件,需要使用事件修饰符native,即可为子组件绑定内置事件。

<Student ref="stu" @click.native="show"></Student>

4. 组件自定义事件 总结

  1. 一种组件间通信的方式,适用于:子组件 ===> 父组件
  2. 使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
  3. 绑定自定义事件:
  1. 第一种方式,在父组件中:<Demo @atguigu="test"/><Demo v-on:atguigu="test"/>
  2. 第二种方式,在父组件中:
<Demo ref="demo"/>
......
mounted(){
   this.$refs.xxx.$on('atguigu',this.test)
}
  1. 若想让自定义事件只能触发一次,可以使用once修饰符,或$once方法。
  1. 触发自定义事件:this.$emit('atguigu',数据)
  2. 解绑自定义事件this.$off('atguigu')
  3. 组件上也可以绑定原生DOM事件,需要使用native修饰符。
  4. 注意:通过this.$refs.xxx.$on('atguigu',回调)绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!



相关文章
|
9月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
754 2
|
8月前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
630 137
|
12月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
1187 0
|
11月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
763 1
|
11月前
|
JavaScript 安全
在 Vue 中,如何在回调函数中正确使用 this?
在 Vue 中,如何在回调函数中正确使用 this?
536 0
|
JavaScript
Vue的非父子组件之间传值
全局事件总线 一种组件间通信的方式,适用于任意组件间通信
283 0
|
缓存 JavaScript 前端开发
Vue Props、Slot、v-once、非父子组件间的传值....
Vue Props、Slot、v-once、非父子组件间的传值....
260 0
|
JavaScript
Vue中父子组件传值
先在⽗组件中给⼦组件的⾃定义属性绑定⼀个⽗组件的变量
270 0
|
JavaScript
vue 组件传值
vue 组件传值
235 0
|
JavaScript
vue父子组件传值
vue父子组件传值