自定义事件分发,$emit
先看懂vue插槽(slot),在看自定义事件分发
vue slot插槽
因为自定义component组件无法直接访问vue实例(vm)中的数据和方法,所以如果在自定义组件中定义一个事件,去改变vm中的数据是无法直接实现。但是视图层(页面标签中)即可以访问vm,也可以访问自定义组件;那么通过组件控制视图层,再由视图层调用vm中的方法,就可以实现component间接调用vm中的方法,这就是$emit在做的一个操作。
<div id = "vueli3">
<course v-for="(course,caindex) in courses">
<template v-slot:slot-a>
<category :category="course.category"></category>
</template>
<template v-slot:slot-b>
<course-name v-for="(name,naindex) in course.courseNames" @remove="remove(caindex,naindex)" :courseName="name" ></course-name><!--通过 @remove 自定义了一个事件叫做remove事件(可以类比想象成一个click事件),事件触发时(具体触发动作在组件中实现)调用app2中的remove(参数一,参数二)方法,-->
</template>
</course>
</div>
const app2 = Vue.createApp({
data(){
return{
courses: [
{category: "编程语言",courseNames:["golang","python","java ee"]},
{category: "技术框架",courseNames:["element UI","SpringMvc","SpringBoot"]},
{category: "编译工具",courseNames:["IDEA","vscode","notepad++"]}
]
}
},
methods:{
remove(caindex,naindex){//删除数据方法
if(this.courses[caindex].courseNames.length == 1){
this.courses.splice(caindex,1)
}else{
this.courses[caindex].courseNames.splice(naindex,1)
}
console.log(this.courses)
}
}
})
app2.component("course",{
template:`<div>
<slot name="slot-a"></slot>
<ul>
<slot name="slot-b"></slot>
</ul>
</div>`
})
app2.component("category",{
props: ["category"],
template:"<h3>{{category}}</h3>"
})
app2.component("course-name",{
props: ["coursename"],
template:`<li>
<span>{{coursename}}</span>
<button @click='remove()'>删除</button>
</li>`,
methods:{
remove(){//组件中的点击事件触发该remove函数
this.$emit("remove");//通过$emit("视图层中的自定义事件名",参数1,参数2...)触发自定义事件。
}
}
})
app2.mount("#vueli3")