经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » Vue.js » 查看文章
Vue中$on和$emit的实现原理分析
来源:jb51  时间:2022/5/30 9:37:33  对本文有异议

Vue中发布订阅模式

在Vue中采用了发布订阅模式,典型的兄弟组件间的通信$on和$emit

发布订阅模式:(订阅者、发布者、信号中心)

一个发布者$emit发布一个事件到信号中心 eventBus ,订阅者们 $on 通过信号中心收到该事件,进行处理

在这里模拟一个自定义事件 $on和$emit事件

  1. class EventBus{
  2. constructor(){
  3. // 1.处理事件对应的处理函数
  4. this.sub = {}
  5. }
  6. $on(event,fn){
  7. if(!this.sub[event]){
  8. // 2.判断sub是否已经存在该事件了,没有的话就赋值一个数组,用来存储触发函数
  9. this.sub[event] = []
  10. }
  11. // 3.将函数push到对应的事件中
  12. this.sub[event].push(fn)
  13. }
  14. $emit(event){
  15. if(this.sub[event]){
  16. this.sub[event].forEach(fn=>{
  17. fn() //4.执行对应事件中的处理函数
  18. })
  19. }
  20. }
  21. }
  22. // 信号中心
  23. const vm = new EventBus()
  24. // 订阅事件
  25. vm.$on('click',()=>{console.log('触发了click事件')})
  26. vm.$on('change',()=>{console.log('触发了change事件')})
  27. // 发布订阅
  28. vm.$emit('click')
  29. vm.$emit('change')

$emit和$on用法深挖

俗称的 e m i t 和 emit和 emit和on就是消费和定义,咱们在代码中讲解

  1. <body>
  2. <div id="app">
  3. <button @click="add">测试</button>
  4.  
  5. </div>
  6. <script>
  7. var vm = new Vue({
  8. el: '#app',
  9. data: {
  10. message:'ok'
  11. },
  12. created() {
  13. this.$on('my_event',this.datalist)
  14. },
  15. methods: {
  16. datalist(e){
  17. console.log(this.message,e);
  18. },
  19. add(){
  20. this.$emit('my_event','hello wu')
  21. }
  22. }
  23. });
  24. </script>
  25. </body>

首先剖析一下$on的原理实现

先在create加个断点

我们会发现他会跳到on的源码中

我们传入的参数是两个,第一个是我们事件的名称,第二个是我们事件处理方法对应的event和fn

  • 首先他把this传给vm
  • 然后判断event是不是一个数组,如果是个数组他就会以循环的方式进行赋值,继续执行on的迭代方法,如果不是数组进入else的逻辑判断去找他是不是包含了event,如果不包含他会自己创建个event设置成空数组,把新建的处理函数push进去,这说明我们在定义个事件的时候,是可以同时为一个事件定义多个执行方法,最后找到定义的方法并返回
  • 定义第二种方法看代码
  1. var vm = new Vue({
  2. el: '#app',
  3. data: {
  4. message:'ok'
  5. },
  6. created() {
  7. this.$on('my_event',this.datalist)
  8. this.$on('my_event',this.datalist2)
  9. },
  10. methods: {
  11. datalist(e){
  12. console.log(this.message,e);
  13. },
  14. datalist2(e){
  15. console.log('我是第二种方法',e);
  16. },
  17. add(){
  18. this.$emit('my_event','hello wu')
  19. }
  20. }
  21. });

说明定义多个执行方法也是没问题的

有一点要记住先定义的先触发

还有一个点他是可以是个数组,在不同的事件绑定同一个处理方法,如下代码

  1. var vm = new Vue({
  2. el: '#app',
  3. data: {
  4. message:'ok'
  5. },
  6. created() {
  7. this.$on(['my_event','my_event2'],this.datalist)
  8. console.log(this._events);
  9. // this.$on('my_event',this.datalist2)
  10. },
  11. methods: {
  12. datalist(e){
  13. console.log(this.message,e);
  14. },
  15. datalist2(e){
  16. console.log('我是第二种方法',e);
  17. },
  18. add(){
  19. this.$emit('my_event2','hello wu')
  20. }
  21. }
  22. });

换成第二个数组他还是可以实现

分析$emit

先打个断点

1.emit的源码

2.关键的一步:先通过名称改成小写后然后直接从我们vue实例下划线events这个对象当中拿出事件对应的方法,如果找不到什么都不做,直接返回回来,找的话,第一步先判断cbs的长度打不打与1,因为他有可能是个数组,多个处理函数如果大于一就变成了一个数组,如果等于一的话直接返回cbs.

第二步他对arguments做了处理把后面的参数变成数组,第一个不要了 ,因为事件名称他用完了,紧接着他对cbs做了个循环,

这个函数是捕获处理异常,执行try catch,所以说如果执行emit出了错误他不会崩溃,会抛出错误,这个地方做的还不赖 最后把res返回

总结

可以通过源码去理解事半功倍噢

通过源码分析我们会知道on方法在定义的时候他可以定义多个事件,也可以为同个事件绑定多个处理函数,在定义中还可以是数组

在emit当中进行trycate的处理,所以我们抛出异常的时候我们不会中断整个程序而崩溃

以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号