1️⃣ 监听组件事件
$on() / v-on - 监听事件 $emit() - 把事件沿着作用域链向上派送
父级组件可以像处理 native DOM 事件一样通过 v-on 监听子组件实例的任意事件:
同时子组件可以通过调用内建的 $emit 方法并传入事件名称来触发一个事件:
1️⃣ 事件名
不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。举个例子,如果触发一个 camelCase 名字的事件:
则监听这个名字的 kebab-case 版本是不会有任何效果的:
<h1 @click="$emit('eventsOne', '向父组件传的参数')">点击</h1>
<component-one @events-one="method"></component-one>
不同于组件和 prop,事件名不会被用作一个 JavaScript 变量名或 property 名,所以就没有理由使用 camelCase 或 PascalCase 了。并且 v-on 事件监听器在 DOM 模板中会被自动转换为全小写 (因为 HTML 是大小写不敏感的),所以 v-on:myEvent 将会变成 v-on:myevent——导致 myEvent 不可能被监听到。
因此,我们推荐始终使用 kebab-case 的事件名。
<h1 @click="$emit('events-one', '向父组件传的参数')">点击</h1>
<component-one @events-one="method"></component-one>
1️⃣ 使用事件抛出一个值
<template>
<div id="app">
<component-one @events="method"></component-one>
</div>
</template>
<script>
import ComponentOne from "./components/ComponentOne.vue";
export default {
components: { ComponentOne },
methods: {
method(e) {
console.log("子组件抛出一个事件");
console.log(e);
},
},
};
</script>
<template>
<div class="component-one">
<!-- $emit() 可以写入方法中抛出 -->
<h1 @click="$emit('events', '向父组件传的参数')">点击</h1>
</div>
</template>
1️⃣ 解绑事件
this.$off('事件名') // 解绑单个事件
this.$off(['事件名', '事件名']) // 解绑多个事件
this.$off() // 解绑所有组件事件
1️⃣ 将原生事件绑定到组件
你可能有很多次想要在一个组件的根元素上直接监听一个原生事件。这时,你可以使用 v-on 的 .native 修饰符:
// 父组件
<template>
<div id="app">
<component-one @focus.native="onFocus"></component-one>
</div>
</template>
<script>
import ComponentOne from "./components/ComponentOne.vue";
export default {
components: { ComponentOne },
methods: {
onFocus() {
console.log("子组件 Focus");
},
},
};
</script>
// 子组件
<template>
<input type="text" />
</template>
在有的时候这是很有用的,不过在你尝试监听一个类似 的非常特定的元素时,这并不是个好主意。比如上述
// 子组件
<template>
<label>
<input type="text" />
</label>
</template>
这时,父级的 .native 监听器将静默失败。它不会产生任何报错,但是 onFocus 处理函数不会如你预期地被调用。
为了解决这个问题,Vue 提供了一个 $listeners
1. $listeners 包含了父作用域中的 ( 不含 .native 修饰器的 ) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。
// 子组件
<template>
<label>
<input type="text" v-on="$listeners" />
</label>
</template>
<script>
export default {
mounted() {
console.log(this.$listeners);
},
};
</script>
有了这个 $listeners property,你就可以配合 v-on=”$listeners” 将所有的事件监听器指向这个组件的某个特定的子元素。
// 父组件
<template>
<div id="app">
<component-one @focus="onFocus" @blur="onBlur"></component-one>
</div>
</template>
<script>
import ComponentOne from "./components/ComponentOne.vue";
export default {
components: { ComponentOne },
methods: {
onFocus() {
console.log("子组件 Focus");
},
onBlur() {
console.log("子组件 Blur");
},
},
};
</script>
// 子组件
<template>
<label>
<input type="text" v-on="$listeners" />
</label>
</template>
<script>
export default {
mounted() {
console.log(this.$listeners);
},
};
</script>