Backbone Events 源码笔记
用了backbone一段时间了,做一些笔记和总结,看的源码是1.12
backbone有events,model,collection,histoty,router,view这些模块,其中events是最基础的,其他的模块的prototype全部都扩展了他,所以events是非常重要的,真的很重要,还好代码比较简单,也比较好理解
这个里面的代码是从backbone里面剥离出来,然后一点一点研究和调试出来的,可以单独运行,依赖underscore
1 (function(){ 2 this.Backbone = {}; 3 var array = []; 4 var slice = array.slice; 5 // Regular expression used to split event strings. 6 //劈开eventsApi函数里面传入name,如果name是带空格的字符串 7 var eventSplitter = /\s+/; 8 9 // Implement fancy features of the Events API such as multiple event 10 // names `"change blur"` and jQuery-style event maps `{change: action}` 11 // in terms of the existing API. 12 //如果传入的name(这个对应绑定 删除 触发 监听的事件名)为obj 或者是带空格的字符串,则批量进行相关的操作 13 var eventsApi = function(obj, action, name, rest) { 14 if (!name) return true; 15 16 // Handle event maps. 17 if (typeof name === 'object') { 18 for (var key in name) { 19 obj[action].apply(obj, [key, name[key]].concat(rest)); 20 } 21 return false; 22 } 23 24 // Handle space separated event names. 25 if (eventSplitter.test(name)) { 26 var names = name.split(eventSplitter); 27 for (var i = 0, length = names.length; i < length; i++) { 28 obj[action].apply(obj, [names[i]].concat(rest)); 29 } 30 return false; 31 } 32 33 return true; 34 }; 35 36 37 38 var Events = Backbone.Events = { 39 // Bind an event to a `callback` function. Passing `"all"` will bind 40 // the callback to all events fired. 41 // 参数的传入为 事件名, 回调, 回调里面this指向的对象 42 on: function(name, callback, context) { 43 if (!eventsApi(this, 'on', name, [callback, context]) || !callback) return this; 44 //对象内部生成一个_events对象 key对应事件名, value为一个数组,里面添加相关的回调函数 45 this._events || (this._events = {}); 46 var events = this._events[name] || (this._events[name] = []); 47 //第3个和第4个参数,表示回调函数触发的是偶, 函数里面this的指向 48 events.push({callback: callback, context: context, ctx: context || this}); 49 return this; 50 }, 51 // Bind an event to only be triggered a single time. After the first time 52 // the callback is invoked, it will be removed. 53 // 跟on一样的入参 ,他只会执行一次 54 once: function(name, callback, context) { 55 if (!eventsApi(this, 'once', name, [callback, context]) || !callback) return this; 56 var self = this; 57 //真正绑定进_.events的事故once 而不是callback,当once执行完一次后,就从_events上面删除掉了 58 var once = _.once(function() { 59 self.off(name, once); 60 callback.apply(this, arguments); 61 }); 62 once._callback = callback; 63 return this.on(name, once, context); 64 }, 65 66 // Trigger one or many events, firing all bound callbacks. Callbacks are 67 // passed the same arguments as `trigger` is, apart from the event name 68 // (unless you're listening on `"all"`, which will cause your callback to 69 // receive the true name of the event as the first argument). 70 trigger: function(name) { 71 if (!this._events) return this; 72 var args = slice.call(arguments, 1); 73 if (!eventsApi(this, 'trigger', name, args)) return this; 74 var events = this._events[name]; 75 var allEvents = this._events.all; 76 //通过name 找到对应的回调数组 依次执行里面的回调 77 if (events) triggerEvents(events, args); 78 //查看是否绑定了all事件 如果绑定也会出阿发 79 if (allEvents) triggerEvents(allEvents, arguments); 80 return this; 81 }, 82 83 // Remove one or many callbacks. If `context` is null, removes all 84 // callbacks with that function. If `callback` is null, removes all 85 // callbacks for the event. If `name` is null, removes all bound 86 // callbacks for all events. 87 off: function(name, callback, context) { 88 if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this; 89 90 // Remove all callbacks for all events. 91 //如果参数不存在 就移除所有的事件 92 if (!name && !callback && !context) { 93 this._events = void 0; 94 return this; 95 } 96 97 var names = name ? [name] : _.keys(this._events); 98 for (var i = 0, length = names.length; i < length; i++) { 99 name = names[i]; 100 101 // Bail out if there are no events stored. 102 var events = this._events[name]; 103 if (!events) continue; 104 105 // Remove all callbacks for this event. 106 //如果只传递name这一个参数 就删除name对应的整个数组 107 if (!callback && !context) { 108 delete this._events[name]; 109 continue; 110 } 111 112 // Find any remaining events. 113 // 114 //如果如果传递了第2个参数 只删除_events[name]里面对应的callback 115 //如果传递了第2个参数,第3个参数,还要判断_events[name]里面的callback是否等于第2个参数,context是否等于第3个参数 116 //把那么不符合条件的用remaining保存起来 117 //然后用this._events[name] = remaining替换掉之前的 118 var remaining = []; 119 for (var j = 0, k = events.length; j < k; j++) { 120 var event = events[j]; 121 if ( 122 callback && callback !== event.callback && 123 callback !== event.callback._callback || 124 context && context !== event.context 125 ) { 126 remaining.push(event); 127 } 128 } 129 130 // Replace events if there are any remaining. Otherwise, clean up. 131 if (remaining.length) { 132 this._events[name] = remaining; 133 } else { 134 delete this._events[name]; 135 } 136 } 137 138 return this; 139 }, 140 // Tell this object to stop listening to either specific events ... or 141 // to every object it's currently listening to. 142 stopListening: function(obj, name, callback) { 143 var listeningTo = this._listeningTo; 144 if (!listeningTo) return this; 145 var remove = !name && !callback; 146 if (!callback && typeof name === 'object') callback = this; 147 if (obj) (listeningTo = {})[obj._listenId] = obj; 148 for (var id in listeningTo) { 149 obj = listeningTo[id]; 150 obj.off(name, callback, this); 151 if (remove || _.isEmpty(obj._events)) delete this._listeningTo[id]; 152 } 153 return this; 154 } 155 } 156 157 var listenMethods = {listenTo: 'on', listenToOnce: 'once'}; 158 159 // Inversion-of-control versions of `on` and `once`. Tell *this* object to 160 // listen to an event in another object ... keeping track of what it's 161 // listening to. 162 // on listenTo 163 _.each(listenMethods, function(implementation, method) { 164 Events[method] = function(obj, name, callback) { 165 //obj 为被监听的对象 166 //name 为被监听的事件名 167 // callback 是obj触发了name事件后, 别监听到了 然后执行的回调 168 var listeningTo = this._listeningTo || (this._listeningTo = {}); 169 var id = obj._listenId || (obj._listenId = _.uniqueId('l')); 170 //给监听对象添加一个_listeningTo的属性 它的值是一个对象key为_listenId value为被监听的对象 171 //被监听对象添加一个_listenId的属性 它的值为_listenId 172 listeningTo[id] = obj; 173 174 if (!callback && typeof name === 'object') callback = this; 175 obj[implementation](name, callback, this); 176 return this; 177 }; 178 }); 179 180 // A difficult-to-believe, but optimized internal dispatch function for 181 // triggering events. Tries to keep the usual cases speedy (most internal 182 // Backbone events have 3 arguments). 183 //批量处理_events里面的回调事件的东西 184 //参数小于等于3个用call 大于3个用apply 为毛会这样 185 var triggerEvents = function(events, args) { 186 var ev, i = -1, l = events.length, a1 = args[0], a2 = args[1], a3 = args[2]; 187 switch (args.length) { 188 case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx); return; 189 case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1); return; 190 case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2); return; 191 case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, a1, a2, a3); return; 192 default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args); return; 193 } 194 }; 195 })();
View Code
Backbone.Events
Events主要就是对object进行绑定,触发,删除,监听,它有以下一些方法
on bind 绑定事件
trigger 触发绑定事件
off unbind 移除绑定事件
listenTo 监听对象
stopListening 停止监听
on object.on(event, callback, [context])
绑定callback函数到object对象。 当事件触发时执行回调函数callback。第一个参数是事件名,第2个参数是绑定的事件 第3个参数是一个对象,callback里面如果有this,则this指向第3个参数,如果没有传递第3个参数则callback里面的this指向object本身
当绑定上一个事件的时候,该object会产生一个_events的属性,该属性是一个object类型,key对应的是事件名,value对应的是一个数组,数组里面放的是所有的回调事件
当触发一个事件的时候,它会遍历_.events,根据传递的事件名,查找相关的回调事件,然后执行。如果绑定了all,则只要调用了trigger,就会调用all下面的所有的回调
一些例子
一个object可以绑定多个事件,同一个事件可以有多个回调
var test = {};_.extend(test,Backbone.Events);test.on("a",function(){alert(1)}); test.on("a",function(){alert(11)});test.on("b",function(){alert(2)});test.trigger("a");test.trigger("b");//test绑定了2个事件a,b a绑定了2个回调函数
obj可以批量绑定事件,就是第一个参数是个对象
var obj = {c:1}var test={};_.extend(test,Backbone.Events);test.on({"a" : function(){alert(1111)},"b" : function(){alert(this.c)}},obj);test.trigger("b") //弹出1//可以一次绑定2个事件a,b 传入的第3个参数是个obj,所以回调执行的时候this指向obj
如果指定绑定事件名为all,触发任何绑定事件的时候都会触发该事件
var test = {};_.extend(test,Backbone.Events);test.on("a",function(){alert(1)});test.on("all",function(){alert(111)});test.trigger("a"); //触发a事件 也会自动触发all事件
once object.on(event, callback, [context])
绑定callback函数到object对象。 当事件触发时执行回调函数callback。 第3个参数是一个对象,callback里面如果有this,则this指向第3个参数。
该绑定事件只能触发一次,然后就会被移除掉
var test = {};_.extend(test,Backbone.Events); test.once("a",function(){alert(1)});console.log(test); //test._events里面是有a属性的test.trigger("a");console.log(test) //test._events里面的a属性就被删除掉了test.trigger("a");
trigger object.trigger(event, [*args])
通过事件名触发对应的回调函数。events后面的参数作为参数传入回调事件里面
var test = {};_.extend(test,Backbone.Events); test.on("a",function(a){alert(a)});test.on("a",function(a,b){alert(a+b)}); test.on("a",function(a,b,c){alert(a+b+c)});test.trigger("a",1,2,3) //依次弹出1,3,6
off object.off([event], [callback], [context])
从object中删除以前绑定的回调函数
第一个参数是事件名
第2个参数是指定的函数,如果传了,就只删除绑定在object上的该函数,如果没传,则移除所有的函数
第3个参数是指定对象,如果绑定的时候调用回调指定了对象,删除的时候也要把该对象带上
如果调用off的时候不传递参数,则删除所有的绑定事件
var test = {}; _.extend(test,Backbone.Events); test.on("a",function(){alert(1)}) test.on("b",function(){alert(1)}) console.log(test._events) test.off() console.log(test._events) //删除后test._events就是空的了
如果指定了删除的事件名,并且传递了第2个参数,而且第2个参数是就是传入的回调的事件,则只删除该指定了回调函数
var test = {}; _.extend(test,Backbone.Events); var aFun = function(){alert(1)} test.on("a",aFun ) test.on("a",function(){alert(1)}) console.log(test._events); test.off("a",aFun) console.log(test._events); //只删除了第二个参数指定的回调函数
listenTo object.listenTo(other, event, callback)
object监听other对象上的指定的方法名上(比如a),如果other触发a,则也会触发监听的回调(callback)
当一个对象监听其他对象的事件名的时候(比如a,b,2个对象,b绑定haha事件,a监听b的haha事件),a对象会生成_listeningTo的对象,根据_.uniqueId("l")生成的值来做key,value则是b这个对象了。b对象则会生成一个属性_listenId,他的值就是前面_.uniqueId("l")生成的值, 然后如果传入了监听事件的回调函数 再b._events.haha的回调数组中加入该函数,当b触发haha的时候也就会触发该函数了。
listenTo还是很重要的,比如一个view,初始化的时候就去listento一个model,当model,的时候就会自动通知view去渲染页面
第一个参数是要监听的对象,
第二个参数是需要监听的事件名
第三个参数是当被监听者处罚了该事件,执行的回调
var test = {}; var other = {}; _.extend(test,Backbone.Events); _.extend(other,Backbone.Events); other.on("a",function(){alert(1)}) other.on("a",function(){alert(2)}) test.listenTo(other,"a",function(){alert("test")}) other.trigger("a") //test监听other,当other触发a时,先执行完ohter自己绑定的回调,在执行监听回调
转载于:https://www.cnblogs.com/wtcsy/p/3826307.html
Backbone Events 源码笔记相关推荐
- redis源码笔记 - 刘浩de技术博客 - 博客园
redis源码笔记 - 刘浩de技术博客 - 博客园 redis源码笔记 - 刘浩de技术博客 - 博客园 redis源码笔记 记录发现的一个hiredis的bug 摘要: hiredis是redis ...
- angularjs源码笔记(3)--injector
2019独角兽企业重金招聘Python工程师标准>>> 简介 injector是用来做参数自动注入的,例如 function fn ($http, $scope, aService) ...
- spring aop原理_Spring知识点总结!已整理成142页离线文档(源码笔记+思维导图)...
写在前面 由于Spring家族的东西很多,一次性写完也不太现实.所以这一次先更新Spring[最核心]的知识点:AOP和IOC 无论是入门还是面试,理解AOP和IOC都是非常重要的.在面试的时候,我没 ...
- 数据结构源码笔记(C语言描述)汇总
数据结构源码笔记(C语言):英文单词按字典序排序的基数排序 数据结构源码笔记(C语言):直接插入排序 数据结构源码笔记(C语言):直接选择排序 数据结构源码笔记(C语言):置换-选择算法 数据结构源码 ...
- 数据结构源码笔记(C语言):英文单词按字典序排序的基数排序
//实现英文单词按字典序排序的基数排序算法#include<stdio.h> #include<malloc.h> #include<string.h>#defin ...
- 数据结构源码笔记(C语言):索引文件建立和查找
//实现索引文件建立和查找算法#include<stdio.h> #include<malloc.h> #include<string.h> #include< ...
- 数据结构源码笔记(C语言):快速排序
//实现快速排序算法 #include<stdio.h> #include<malloc.h> #define MAXE 20typedef int KeyType; type ...
- 数据结构源码笔记(C语言):冒泡排序
//冒泡排序算法实现 #include<stdio.h> #include<malloc.h> #define MAXE 20typedef int KeyType; type ...
- 数据结构源码笔记(C语言):希尔插入排序
//实现希尔插入排序算法 #include<stdio.h> #include<malloc.h> #define MAXE 20typedef int KeyType; ty ...
- 数据结构源码笔记(C语言):直接插入排序
//实现直接插入排序算法#include<stdio.h> #include<malloc.h> #define MAXE 20typedef int KeyType; typ ...
最新文章
- java实验系统常用类,Java的常用系统类
- Halcon模板匹配之读取dxf文件生成xld与后续操作
- sscanf fscanf函数格式化输入遇到\n问题
- 集训01-03 (c++实现)
- Spring源码分析之ProxyFactoryBean方式实现Aop功能的分析
- Linux 命令(101)—— bc 命令
- 如何利用机器学习进行海量数据挖掘
- 配置中心.php,FastD 最佳实践二: 构建配置中心
- UDS协议的项目应用
- 大数据的四个典型特征
- CentOS7安装oh-my-zsh(github start Top 10)
- 打开计算机出现酷我音乐删不掉,删除 “我的电脑” 里的 “酷我音乐” 快捷方式...
- dvi线支持多少分辨率_dvi接口有哪几种_dvi支持最大分辨率
- 纽约州立大学石溪分校肖可瓅:数据驱动的金融研究
- 什么是外包?定义、最佳实践、挑战和建议
- 使用navicat进行mysql数据库拷贝
- 【开关电源一】电源拓扑之buck、boost、buck-boost
- 告诉你猪身上最香的部位是什么?五花肉不是最香
- 腾讯云服务器8核16G18M配置测评
- 【结论】加工生产调度
热门文章
- Linux ssh 文件 authorized_keys 和 known_hosts
- 测试开发工作者日记:2020.6.10-6.11
- 高德地图API之定位API
- Linux查看开机自动运行的服务
- Java实现 定义一个名为Rectangle的类表示矩形 求面积周长
- IDEA2017配置springmvc遇到的错误
- Global Illumination_Lens Flare(镜头光晕)
- codeforces 136A(Presents) Java
- 嗅探原理与反嗅探技术详解
- 比伯女友首谈私生子事件 挺男友:事实胜于诡辩