Js的内置事件
Js的内置事件有click、keyup、mouseleave、mouseenter....,这些我们是要给html使用,比如给h1一个click事件,给input一个keyup事件。
那么现在我们就要打造一个自定义的事件,比如:aa、bb、cc(自己定义的),这些我们是要给组件使用的
准备
把之前我写过的《scoped样式》里的components和App.vue复制下来
把里面代码弄简单点,写的更便于观察一些
下面就是改完后的网页效果图
为了好看一点,我又加了一些样式
最后效果是这样的
实现将子组件的数据传到父组件
一:通过父组件给子组件传递函数类型的props实现
点击school部分的一个按钮,将学校名和地址传到App上
用props实现,父组件传递一个方法给子组件,子组件用props接收,子组件通过接收到的方法将数据传给父组件
在网页点击按钮后,App就收到学校名了
二:通过父组件给子组件绑定一个自定义事件实现
第一种写法,使用@或v-on
点击student部分的一个按钮,将学生名传到App上
通过v-on绑定一个方法,v-on在Student组件上就是给Student组件的实例对象vc绑定一个名叫xuesheng的事件,如果有人触发了这个xuesheng事件,那么demo函数就会被调用。
先配置一下demo,只要demo被调用了,就会提示我们
那么现在只要我们触发Student里的xuesheng事件,就可以调用demo了,我们先给Mystudent一个点击事件,
xuesheng事件在MyStudent的vc里,我们直接就可以获取到,但是如果要触发该事件,就要通过$emit(emit:散发;发出)来触发
点击按钮,demo就被调用了
如果要上传学生名,就要传参数,直接在后面加一个参数就可以
在App也就收到了参数
在网页上点击按钮,就可以将学生名上传到App上了
为了看起来更整齐一点,我将demo改成getStudentname
将上面MySchool里的upload也改成sendSchoolname
对了,v-on可以简写,如下
第二种写法,使用ref(灵活性强)
在App使用ref,然后只要我通过this.$refs.student就可以在App上拿到Student组件的实例对象vc
然后我再App方法上写一个钩子mounted,只要App挂载完毕就拿student的实例对象
然后在后面写一个$on('xuesheng',this.getStudentname),表示的是当触发这个xuesheng事件就调用getStudentname函数
我的mounted放错位置了,我放method里边去了,应该放在外面
修改过来后,在网页点击按钮后,就可以得到学生名了
为什么说第二种写法比第一种写法的灵活性强,因为如果我想等个3秒后再绑定,那么第一种写法就没法操作,而第二种写法就可以
然后再网页上如果你刷新后前3秒还没绑定,所以我们点击按钮后得不到学生名,3秒后再点击按钮,就可以得到学生名了
获取一次学生名
第二种写法
我们无数次点击按钮,就可以无数次获得学生名
如果我希望只能获取一次学生名,那么就需要换一个api,将once
这样网页你再点击多少次它都只获取一次学生名
第一种写法
那么如果我要第一种写法,只获取一次学生名,那么就在xuesheng后面加上once
网页上点击按钮,得到的也一样的效果
接收多个参数
如果我想传递多个参数也是可以的,在第一种写法的基础上,直接在this.name的后面直接加上其它的参数
然后在App上接收
在网页上点击按钮后,你就可以看到其它传递出来的参数
一般来说,我们不会传递那么多的参数,如果需要传递那么多的参数,我们一般会包在一个对象里面,再传递;对ES6很熟的同学,知道我们可以通过...a来将多个参数包裹在一个a数组里输出,前面参数正常传
把参数包裹在a里,再将a数组输出
网页上点击按钮后,就可以输出包裹着后面参数的数组
但一般不用a用的是params
因为后面章节要用这些代码,所以我先把once删掉
平时用两种写法都可以,只是我下个文章用的是第一种写法,所以我把第二种写法先注释掉
本结用的主要代码如下:
MySchool.vue
<template>
<div class="school">
<h1>学校名:{{ name }}</h1>
<h1>学校地址:{{ address }}</h1>
<button @click="sendSchoolname">上传学校名给App</button>
</div>
</template>
<script>
// 组件交互相关的代码(数据、方法等等)
export default {
name: "MySchool",
props: ["getSchoolname"],
data() {
return {
name: "南大",
address: "南京",
};
},
methods:{
sendSchoolname(){
this.getSchoolname(this.name)
}
}
};
</script>
<style scoped>
.school {
background-color: orange;
padding: 5px;
}
</style>
MyStudent.vue
<template>
<div class="student">
<h1>学校姓名:{{ name }}</h1>
<h1>学生年龄:{{ age }}</h1>
<button @click="sendStudentname">上传学生名给App</button>
</div>
</template>
<script>
// 组件交互相关的代码(数据、方法等等)
export default {
name: "MyStudent",
data() {
return {
name: "小蒲",
age: 18,
};
},
methods: {
sendStudentname() {
// 触发Student组件实例对象上的xuesheng事件
this.$emit("xuesheng", this.name, 111, 222, 333);
},
},
};
</script>
<style lang="less">
.student {
background-color: pink;
padding: 5px;
margin-top: 30px;
}
</style>
App.vue
<template>
<div class="App">
<h1>{{ msg }}</h1>
<!-- <h2>{{ Schoolname }}</h2> -->
<!-- 通过父组件给子组件传递函数类型的props实现:子给父传递数据 -->
<School :getSchoolname="getSchoolname" />
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on)-->
<!-- <Student v-on:xuesheng="getStudentname" /> -->
<Student @xuesheng="getStudentname" />
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref)-->
<!-- <Student ref="student" /> -->
</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: "",
};
},
methods: {
getSchoolname(name) {
console.log("App收到了学校名", name);
// this.Schoolname = name;
},
getStudentname(name, ...params) {
console.log("App收到了学生名", name, params);
},
},
// mounted() {
// setTimeout(() => {
// // this.$refs.student.$on("xuesheng", this.getStudentname);
// this.$refs.student.$once("xuesheng", this.getStudentname)(一次性);
// }, 3000);
// },
};
</script>
<style>
.App {
background-color: gray;
padding: 5px;
}
</style>