处理可以使用原生的 DOM
事件, v-on
也可以触发组件内部的自定义事件,调用 this.$emit("事件名")
就可以触发一个自定义事件.
$emit()
触发事件函数接受一个自定义事件的事件名以及其他任何给事件函数传递的参数. 然后就可以在组件上使用 v-on
来绑定这个自定义事件
this.emit("事件名",参数1,参数2.....)
$emit
触发自定义事件$on
绑定自定义事件,可以调用无数次$once
绑定自定义事件,只能触发一次$off
取消自定义事件的绑定基本语法:
this.emit("事件名",参数1,参数2.....)
实例.$on("事件名",function(参数1,参数2....){})
实例.$once("事件名",function(参数1,参数2....){})
this.$off("事件名")
实例代码如下:
<div id="app">
{{count}}
<button @click="clickBtn ">绑定事件</button>
<button @click = "clickBtn2">取消事件绑定</button>
</div>
<script>
let vm = new Vue({
el:"#app",
data:{
count:0,
},
methods:{
clickBtn() {
//触发事件
this.$emit("add");
// this.$emit("count")
},
clickBtn2() {
this.$off("add")
}
},
components: {
// MyCom,
}
})
//绑定一个自定义事件
vm.$on("add",function () {
this.count++
})
//绑定事件只触发一次
vm.$once("count",function () {
this.count++
})
现在我们就可以利用自定义事件让子组件改变父组件的值或者想父组件传参
通过父组件向子组件传值的学习,我们已经知道了 Vue
是单向下行数据流, 子组件更改 props
中的数据不会触发父组件数据的改变, 但是由于响应式原理,父组件数据的改变会导致子组件 props
中值的改变
那么我们怎么才能在子组件中改变父组件中的数据呢???
- 子组件中没有办法改变父组件中的数据,那么我们就让父组件的函数改变自己的数据
- 这样我们就可以在子组件中触发父组件的函数来改变数据,就要通过我们的自定义事件
- 子组件在函数中触发自定义事件,将父组件中更改数据的函数绑定为自定义事件函数.
- 然后父组件中的数据会发生变化,因为响应式原理,子组件中的数据也会发生变化.
看下面的示例代码:
我们通过在子组件中调用父组件的方法,从而达到改变父组件数据的目的:
<div id="app">
<!-- 3.在子组件中绑定自定义事件, 将父组件的方法绑定为自定义事件的处理函数-->
<my-com
:count = "count"
@count="addCount"
></my-com>
</div>
<template id="mycom">
<div>
<h3>我被点击了{{count}}次</h3>
<!-- 1. 子组件通过原生click事件触发子组件自己的函数 -->
<button @click="add">点击+1</button>
</div>
</template>
<script>
let MyCom = ({
props:["count"],
template: "#mycom",
methods: {
add() {
// 2.子子组件函数中触发自定义事件
this.$emit("count");
}
}
})
let vm = new Vue({
el: "#app",
data: {
count: 0
},
components: {
MyCom,
},
methods: {
// 4. 在父组件函数中修改父组件中的数据
addCount() {
this.count++;
}
}
})
</script>
点击数字会增加:
当点击子组件按钮时,在子组件处理函数中触发父组件中的自定义事件,进而触发父组件中自定义事件的自定义函数,然后就会在父组件中修改父组件中的数据.
进而通过 props
响应式,当父组件中的数据改变,子组件中的数据也会发生相应的改变.
我们也知道$emit
方法在触发自定义事件的时候,还可以给自定义事件传参, 这样就可以实现子组件像父组件传参.
通过前面的介绍,我们了解到,我们是在子组件中通过自定义事件触发父组件中的函数, 在父组件中修改数据,
同样我们也可以在子组件中修改数据,然后将修改后的数据通过自定义事件传参的方式,传递给父组件函数,在父组件函数中直接用子组件传过来修改后的数据直接替换父组件中的数据
示例代码如下:
当我们每次点击都让它加2
<div id="app">
<!-- 3.在子组件中绑定自定义事件, 将父组件的方法绑定为自定义事件的处理函数-->
<my-com
:count = "count"
@count="addCount"
></my-com>
</div>
<template id="mycom">
<div>
<h3>我被点击了{{count}}次</h3>
<!-- 1. 子组件通过原生click事件触发子组件自己的函数 -->
<button @click="add">点击+1</button>
</div>
</template>
<script>
let MyCom = ({
props:["count"],
template: "#mycom",
methods: {
add() {
// 2.子子组件函数中触发自定义事件
this.$emit("count",2);
}
}
})
let vm = new Vue({
el: "#app",
data: {
count: 0
},
components: {
MyCom,
},
methods: {
// 4. 在父组件函数中修改父组件中的数据
addCount(value) {
console.log(value);
this.count +=2;
}
}
})
</script>
<div id="app">
<!-- 3.在子组件中绑定自定义事件, 将父组件的方法绑定为该自定义事件的处理函数 -->
<my-com :menu = "menu" @add = "addMenu"></my-com>
</div>
<template id = "MyCom">
<div>
<ol >
<li v-for = "(food,index) in menu" :key="index">
{{food.name }}: {{ food.price}}
</li>
</ol>
<!-- 1.子组件通过原生的click触发子组件中的自定义函数-->
<button @click = "addSon">点击添加菜品</button>
</div>
</template>
<script>
let MyCom = ({
props:["menu"],
template:"#MyCom",
methods:{
addSon(){
// 2.子组件函数中触发自定义事件,有传参
this.$emit("add",{
name:"酸辣土豆丝",
price:9,
})
}
}
})
let vm = new Vue({
el:"#app",
data:{
menu:[
{
name:"西红柿炒鸡蛋",
price:10,
},
{
name:"辣椒炒肉",
price:15,
},
]
},
methods:{
//4. 在父组件函数中修改父组件的数据,value就是传递的参数
addMenu(value) {
console.log(value);
this.menu.push(value)
}
},
components: {
MyCom,
}
})
//绑定一个自定义事件
vm.$on("add",function () {
// this.count++
console.log(111)
})