【组件编码流程 组件自定义事件 全局事件总线】
组件编码流程
-
组件化编码流程:
(1).拆分静态组件:组件要按照功能点拆分,命名不要与html元素冲突。
(2).实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用:
1).一个组件在用:放在组件自身即可。
2). 一些组件在用:放在他们共同的父组件上(状态提升)。
(3).实现交互:从绑定事件开始。
-
props适用于:
(1).父组件 ==> 子组件 通信
(2).子组件 ==> 父组件 通信(要求父先给子一个函数)
-
使用v-model时要切记:v-model绑定的值不能是props传过来的值,因为props是不可以修改的!
-
props传过来的若是对象类型的值,修改对象中的属性时Vue不会报错,但不推荐这样做。
组件自定义事件
组件自定义事件是一种组件间通信的方式,适用于:子组件 ===> 父组件
使用场景
A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件的回调在A中)。
绑定自定义事件
第一种方式,在父组件中:<Demo @atguigu="test"/>
或 <Demo v-on:atguigu="test"/>
具体代码
App.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| <template> <div class="app"> <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) --> <Student @atguigu="getStudentName"/> </div> </template>
<script> import Student from './components/Student'
export default { name:'App', components:{Student}, data() { return { msg:'你好啊!', studentName:'' } }, methods: { getStudentName(name,...params){ console.log('App收到了学生名:',name,params) this.studentName = name } } } </script>
<style scoped> .app{ background-color: gray; padding: 5px; } </style>
|
Student.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <template> <div class="student"> <button @click="sendStudentlName">把学生名给App</button> </div> </template>
<script> export default { name:'Student', data() { return { name:'张三', } }, methods: { sendStudentlName(){ //触发Student组件实例身上的atguigu事件 this.$emit('atguigu',this.name,666,888,900) } }, } </script>
<style lang="less" scoped> .student{ background-color: pink; padding: 5px; margin-top: 30px; } </style>
|
第二种方式,在父组件中:
使用 this.refs.xxx.on() 这样写起来更灵活,比如可以加定时器啥的。
具体代码
App.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <template> <div class="app"> <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) --> <Student ref="student"/> </div> </template>
<script> import Student from './components/Student'
export default { name:'App', components:{Student}, data() { return { studentName:'' } }, methods: { getStudentName(name,...params){ console.log('App收到了学生名:',name,params) this.studentName = name }, }, mounted() { this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件 // this.$refs.student.$once('atguigu',this.getStudentName) //绑定自定义事件(一次性) }, } </script>
<style scoped> .app{ background-color: gray; padding: 5px; } </style>
|
Student.vue
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| <template> <div class="student"> <button @click="sendStudentlName">把学生名给App</button> </div> </template>
<script> export default { name:'Student', data() { return { name:'张三', } }, methods: { sendStudentlName(){ //触发Student组件实例身上的atguigu事件 this.$emit('atguigu',this.name,666,888,900) } }, } </script>
<style lang="less" scoped> .student{ background-color: pink; padding: 5px; margin-top: 30px; } </style>
|
若想让自定义事件只能触发一次,可以使用once
修饰符,或$once
方法。
触发自定义事件:this.$emit('atguigu',数据)
使用 this.$emit() 就可以子组件向父组件传数据
注意:通过this.$refs.xxx.$on('atguigu',回调)
绑定自定义事件时,回调要么配置在methods中,要么用箭头函数,否则this指向会出问题!
解绑自定义事件
this.$off('atguigu')
代码
组件使用原生事件
组件上也可以绑定原生DOM事件,需要使用native
修饰符。
如果不用.native修饰符就会被当成自定义事件
1 2
| <!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) --> <Event1 @click.native="handler1"></Event1>
|
1:原生DOM—button可以绑定系统事件----click单击事件等等
2:组件标签— event1可以绑定系统事件(不起作用,因为属于自定义事件)----native(可以把自定义事件变为原生DOM事件)
利用native触发—原理是事件委派
在views/Communication/EventTest/Event1.vue
中:
他的结构是这样的,但是我们在页面中,不管是点击Event1组件,还是其他内容,都可以触发打印,那是因为当前原生DOMclick事件,其实是给子组件的根节点div绑定了点击事件----利用事件委派,所以里面的h2和span也是可以触发打印的

注意:给原生DOM绑定自定义事件没有任何意义的,因为没有办法触发$emit函数
一般是给组件绑定自定义事件在结合on,emit使用
自定义组件中的$event
一般子组件传给父组件的值在methods对象中的函数接收,然而有时想从当前组件传些数据,但是这样就无法接收子组件传来的数据了
这时可以使用$event
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| 子组件 传值 export default { methods: { customEvent() { this.$emit( custom-event , value ) } } } 父组件 接收自定义事件 <template> <div> <my-item v-for="(item, index) in list" @custom-event="customEvent(index, $event)"> </my-list> </div> </template> 接收$event export default { methods: { customEvent(index, e) { console.log(e) } } }
|
全局事件总线
一种可以在任意组件间通信的方式,本质上就是一个对象,它必须满足以下条件
- 所有的组件对象都必须能看见他
- 这个对象必须能够使用onemit$off方法去绑定、触发和解绑事件
使用步骤
-
一种组件间通信的方式,适用于任意组件间通信。
-
安装全局事件总线:
1 2 3 4 5 6 7
| new Vue({ ...... beforeCreate() { Vue.prototype.$bus = this }, ...... })
|
-
使用事件总线:
-
接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件自身。
1 2 3 4 5 6 7
| methods(){ demo(data){......} } ...... mounted() { this.$bus.$on('xxxx',this.demo) }
|
-
提供数据:this.$bus.$emit('xxxx',数据)
-
最好在beforeDestroy
钩子中,用$off去解绑当前组件所用到的事件。
因为销毁的时候只会把组件销毁,不会把$bus上的销毁,下车要把东西带走。
CLI 初始化脚手架 Vue零碎的一些知识
组件通信