准备
为了点击按钮时,触发太多事件,我把一些事件注释掉
将从student上获取到的数据体现在app页面上
方法一
可以通过以下这个方法来做,
这样页面点击按钮就可以在app页面上看到学生名了
方法二
通过this. <math xmlns="http://www.w3.org/1998/Math/MathML"> r e f s . x x x . refs.xxx. </math>refs.xxx.on('xuesheng',回调)绑定自定义事件时,
方式一:回调配置在methods中
上边使用的是第一种写法,我们可以使用一下第二种写法ref
这样也能实现
方式二:this.refs.xxx.on('xuesheng',回调),用箭头函数
如果我把getStudentname方法注释掉,直接在ref下写xuesheng的回调可以吗
可以看到点击按钮后,app还是可以收到数据的
我们把数据放到页面上
点击按钮后,我们可以发现页面上并没有学生名
我们先在控制台看看这个this是什么
网页上点击按钮后,我们可以发现这个this是student组件实例对象vm,所以通过这个方法并不能将学生名放到app页面上
因为是谁触发这个xuesheng方法,那么这个this就是谁,是student触发这个xuesheng,所以这个this就是student的实例对象vm。但是如果把function()改成箭头函数就行了
网页上点击按钮后我们可以发现控制台输出的this是app的实例对象,因而我们可以看到在app上的学生姓名
因为箭头函数没有this所以它就往外找,找到了app的实例对象。为了不用那么麻烦的去区分用普通函数还是箭头函数,我建议还是使用原先的那种方法吧
组件使用原生DOM事件
当作自定义事件
我们添加一个click事件试试,
然后在网页上点击student也就是粉色部分,发现没有任何反应
是因为student把click事件当成自定义事件,如果要触发需要$emit
这样在网页上需要点击上传学生名按钮,才能触发click事件
通过native,通知是原生DOM事件
那么我们要怎么告诉student,click是原生DOM事件呢?我们先把刚才的$emit注释掉
在click后面添加.native就能告诉student,click是原生DOM事件 ,然后把click事件给student最外边的div (这也是为什么组件只能有一个跟元素 )
网页上点击粉色部分,就能触发click事件
组件自定义事件的总结
本结的主要代码如下:
MyStudent.vue
xml
<template>
<div class="student">
<h1>学校姓名:{{ name }}</h1>
<h1>学生年龄:{{ age }}</h1>
<h1>当前求和为:{{ number }}</h1>
<button @click="add">number++</button>
<button @click="sendStudentname">上传学生名给App</button>
<button @click="unbind">解绑xuesheng事件</button>
<button @click="death">销毁当前Student组件的实例对象(vc)</button>
</div>
</template>
<script>
// 组件交互相关的代码(数据、方法等等)
export default {
name: "MyStudent",
data() {
return {
name: "小蒲",
age: 18,
number: 0,
};
},
methods: {
add() {
console.log('Dom原生事件add被调用')
this.number++;
},
sendStudentname() {
// 触发Student组件实例对象上的xuesheng事件
this.$emit("xuesheng", this.name, 111, 222, 333);
// this.$emit("demo");
// this.$emit("click")
},
unbind() {
this.$off("xuesheng"); //只适用解绑一个自定义事件
// this.$off(["xuesheng", "demo"]); //只适用解绑多个自定义事件
// this.$off(); //解绑所有自定义事件
},
death() {
this.$destroy();//销毁了当前Student组件的实例,销毁后所以Student实例的自定义事件全都不奏效了
},
},
};
</script>
<style lang="less">
.student {
background-color: pink;
padding: 5px;
margin-top: 30px;
}
</style>
App.vue
xml
<template>
<div class="App">
<h1>{{ msg }},学生姓名是{{ studentName }}</h1>
<!-- <h2>{{ Schoolname }}</h2> -->
<!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 -->
<School :getSchoolname="getSchoolname" />
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on)-->
<!-- <Student v-on:xuesheng="getStudentname" /> -->
<!-- <Student @xuesheng="getStudentname" @demo="m1" /> -->
<!-- <Student @xuesheng="getStudentname" /> -->
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref)-->
<Student ref="student" @click.native="cl" />
</div>
</template>
<script>
// 引入组件
import School from "./components/MySchool.vue";
import Student from "./components/MyStudent.vue";
export default {
name: "App",
components: { School, Student },
data() {
return {
msg: "你好啊",
// schoolName: "",
studentName: "",
};
},
methods: {
cl() {
alert("123");
},
getSchoolname(name) {
console.log("App收到了学校名", name);
// this.Schoolname = name;
},
getStudentname(name, ...params) {
console.log("App收到了学生名", name, params);
this.studentName = name;
},
// m1(){
// console.log('demo事件被触发了!')
// }
},
mounted() {
// setTimeout(() => {
this.$refs.student.$on("xuesheng", this.getStudentname);
// this.$refs.student.$on("xuesheng", (name, ...params) => {
// console.log("App收到了学生名", name, params);
// console.log(this);
// this.studentName = name;
// });
// this.$refs.student.$once("xuesheng", this.getStudentname)(一次性);
// }, 3000);
},
};
</script>
<style>
.App {
background-color: gray;
padding: 5px;
}
</style>