在 Kendo 中,基类 Class 第一个重要的派生类就是 Observable, 顾名思义,就是一个可观察的对象,也就是观察者模式的基础。

对于观察者模式来说,应该有主题和观察者,这里我们讨论的其实是主题,观察者只需要提供一个回调函数,在适当的时候得到回调就可以了。

对于主题来说,我们应该支持多种观察的目标,如果你使用过 .NET 的事件,这里简直就是将 .NET 的事件轮子重新实现了一下。

1.事件

_events 是用来保存注册的事件信息的存储对象,可以在主题上定义多种事件,每个事件就是 _events 上的一个字段,字段的名字就是事件名称,值是一个数组,用来保存注册到这个事件的回调函数。初始化函数中,将这个对象创建出来。

init: function() {
this._events = {};
},

2. 注册

bind 函数用来进行注册,既可以使用事件名称,处理器方式,也可以一次性注册多个事件,使用事件名称的数组,对应每个事件的处理函数对象来表示。

最关键的实际上是这两行。

 events = that._events[eventName] = that._events[eventName] || [];
events.push(handler);

这里有一些特殊的处理,就是可以注册仅仅执行一次的处理器。在注册的时候,需要将 one 设置为 true,默认是 undefined,也就是多次的。

在一次的情况下,会自动将用户注册的处理器另外保存到 original 中,然后创建一个新的处理器进行注册,这个处理器在执行一次之后,自动将自己从处理器列表中删除。

注册的全部代码

bind: function(eventName, handlers, one) {
var that = this,
idx,
eventNames = typeof eventName === STRING ? [eventName] : eventName,
length,
original,
handler,
handlersIsFunction = typeof handlers === FUNCTION,
events; if (handlers === undefined) {
for (idx in eventName) {
that.bind(idx, eventName[idx]);
}
return that;
} for (idx = 0, length = eventNames.length; idx < length; idx++) {
eventName = eventNames[idx]; handler = handlersIsFunction ? handlers : handlers[eventName]; if (handler) {
if (one) {
original = handler;
handler = function() {
that.unbind(eventName, handler);
original.apply(that, arguments);
};
handler.original = original;
}
events = that._events[eventName] = that._events[eventName] || [];
events.push(handler);
}
} return that;
},

3. 取消注册

对应注册的就是取消注册了。

unbind 完成取消注册的任务,取消注册的时候,有三种选择

  • 全部取消注册的观察者
  • 将某个时间的观察者取消
  • 或者单个取消

所以代码更加简单明了。original 就是在一次性事件中保存的原有处理器。

unbind: function(eventName, handler) {
var that = this,
events = that._events[eventName],
idx; if (eventName === undefined) {
that._events = {};
} else if (events) {
if (handler) {
for (idx = events.length - 1; idx >= 0; idx--) {
if (events[idx] === handler || events[idx].original === handler) {
events.splice(idx, 1);
}
}
} else {
that._events[eventName] = [];
}
} return that;
}

4. 触发处理

触发就比较容易了,提供事件的名称,事件的参数就可以了,直接遍历数组中保存的每一个处理器,通过 call 调用将对象自己作为 this 传递到处理器中。

trigger: function(eventName, e) {
var that = this,
events = that._events[eventName],
idx,
length; if (events) {
e = e || {}; e.sender = that; e._defaultPrevented = false; e.preventDefault = preventDefault; e.isDefaultPrevented = isDefaultPrevented; events = events.slice(); for (idx = 0, length = events.length; idx < length; idx++) {
events[idx].call(that, e);
} return e._defaultPrevented === true;
} return false;
}

5. 辅助函数

额外还提供了两个辅助函数,one 和 first

one 用来检查注册仅仅执行一次的处理器,你会看到通过直接将 bind 的 one 参数设置为 true 来实现的。

one: function(eventNames, handlers) {
return this.bind(eventNames, handlers, true);
},

first 用来将处理函数压入调用对象的最前面, unshift() 方法可向数组的开头添加一个或更多元素,并返回新的长度。

first: function(eventName, handlers) {
var that = this,
idx,
eventNames = typeof eventName === STRING ? [eventName] : eventName,
length,
handler,
handlersIsFunction = typeof handlers === FUNCTION,
events; for (idx = 0, length = eventNames.length; idx < length; idx++) {
eventName = eventNames[idx]; handler = handlersIsFunction ? handlers : handlers[eventName]; if (handler) {
events = that._events[eventName] = that._events[eventName] || [];
events.unshift(handler);
}
} return that;
},

6. 全部代码

全部代码如下:

var Observable = Class.extend({
init: function() {
this._events = {};
}, bind: function(eventName, handlers, one) {
var that = this,
idx,
eventNames = typeof eventName === STRING ? [eventName] : eventName,
length,
original,
handler,
handlersIsFunction = typeof handlers === FUNCTION,
events; if (handlers === undefined) {
for (idx in eventName) {
that.bind(idx, eventName[idx]);
}
return that;
} for (idx = 0, length = eventNames.length; idx < length; idx++) {
eventName = eventNames[idx]; handler = handlersIsFunction ? handlers : handlers[eventName]; if (handler) {
if (one) {
original = handler;
handler = function() {
that.unbind(eventName, handler);
original.apply(that, arguments);
};
handler.original = original;
}
events = that._events[eventName] = that._events[eventName] || [];
events.push(handler);
}
} return that;
}, one: function(eventNames, handlers) {
return this.bind(eventNames, handlers, true);
}, first: function(eventName, handlers) {
var that = this,
idx,
eventNames = typeof eventName === STRING ? [eventName] : eventName,
length,
handler,
handlersIsFunction = typeof handlers === FUNCTION,
events; for (idx = 0, length = eventNames.length; idx < length; idx++) {
eventName = eventNames[idx]; handler = handlersIsFunction ? handlers : handlers[eventName]; if (handler) {
events = that._events[eventName] = that._events[eventName] || [];
events.unshift(handler);
}
} return that;
}, trigger: function(eventName, e) {
var that = this,
events = that._events[eventName],
idx,
length; if (events) {
e = e || {}; e.sender = that; e._defaultPrevented = false; e.preventDefault = preventDefault; e.isDefaultPrevented = isDefaultPrevented; events = events.slice(); for (idx = 0, length = events.length; idx < length; idx++) {
events[idx].call(that, e);
} return e._defaultPrevented === true;
} return false;
}, unbind: function(eventName, handler) {
var that = this,
events = that._events[eventName],
idx; if (eventName === undefined) {
that._events = {};
} else if (events) {
if (handler) {
for (idx = events.length - 1; idx >= 0; idx--) {
if (events[idx] === handler || events[idx].original === handler) {
events.splice(idx, 1);
}
}
} else {
that._events[eventName] = [];
}
} return that;
}
});

7. 总结

Observable 提供了基本的观察者模式支持。

Kendo UI - Observable的更多相关文章

  1. JQuery Kendo UI使用技巧总结

    Kendo UI开发总结 By Gloomyfish on 2013-04-25 在Grid中支持分页刷新:            scrollable: {virtual : true }, 在Gr ...

  2. Kendo UI开发教程(16): Kendo MVVM 数据绑定(五) Events

    本篇和Kendo UI开发教程(14): Kendo MVVM 数据绑定(三) Click类似,为事件绑定的一般形式.Events绑定支持将ViewModel的方法绑定到DOM元素的事件处理(如鼠标事 ...

  3. [转]Upgrading to Async with Entity Framework, MVC, OData AsyncEntitySetController, Kendo UI, Glimpse & Generic Unit of Work Repository Framework v2.0

    本文转自:http://www.tuicool.com/articles/BBVr6z Thanks to everyone for allowing us to give back to the . ...

  4. Kendo UI 单页面应用(三) View

    Kendo UI 单页面应用(三) View view 为屏幕上某个可视部分,可以处理用户事件. View 可以通过 HTML 创建或是通过 script 元素.缺省情况下 View 将其所包含的内容 ...

  5. Web UI开发推荐!Kendo UI for jQuery自定义小部件——使用MVVM

    Kendo UI for jQuery最新试用版下载 Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support f ...

  6. Kendo UI for jQuery使用教程:使用MVVM初始化(二)

    [Kendo UI for jQuery最新试用版下载] Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support ...

  7. kendo ui 实现MVVM

    MVVM                    model----view model----model 实现页面和model之间的动态绑定 grid 支持 events  source  visib ...

  8. Kendo UI Grid 使用总结

    Kendo UI Grid控件的功能强大,这里将常用的一些功能总结一下. Kendo UI Grid 固定列 在使用Gird控件显示数据时,如果数据列过多,会出现横向滚动条,很多情况下,我们希望某些列 ...

  9. kendo ui简介

    Kendo UI Web包含所有创建高速HTML5 web app的必备元素:UI组件.数据源.验证.一个MVVM框架.主题.模板等等. 移动HTML5带UI的开发框架层出不穷,常见的有Sencha ...

随机推荐

  1. 【python】浅谈encode和decode

    对于encode和decode,笔者也是根据自己的理解,有不对的地方还请多多指点. 编码的理解: 1.编码:utf-8,utf-16,gbk,gb2312,gb18030等,编码为了便于理解,可以把它 ...

  2. 战胜忧虑<2>——忙碌可以消除忧虑

    忙碌可以消除忧虑 当你的脑筋空出来时,也会有东西进去补充,是什么呢?通常都是你的感觉.为什么?因为忧虑.恐惧.憎恨.嫉妒.和羡慕等等情绪,都是由我们的思想所控制的,这种情绪都非常猛烈.会把我们思想中所 ...

  3. JSP里的c:url中的/代表站点根目录还是WEB根目录?(待解答)

    <c:url/>使用格式: <c:url var="<string>" scope="<string>" value= ...

  4. HTML标签使用特写

    页面定时刷新标签 //页面定时刷新 <meta http-equiv="> Input标记各种特殊用法 <%--禁止鼠标选择内容--%> <input id=& ...

  5. 328. Odd Even Linked List

    Given a singly linked list, group all odd nodes together followed by the even nodes. Please note her ...

  6. css hack 总结 包括ie6-11,chrome,opera,firefox

    <!DOCTYPE html> <html> <head> <title>Css Hack ie各版本 opera chrome safari fire ...

  7. Php检测文件编码方法

    <?php /** * 检测文件编码 * @param string $file 文件路径 * @return string|null 返回 编码名 或 null */ function det ...

  8. (C#) What is the difference between "const" and "static readonly" ?

    const int a must be initialized initialization must be at compile time readonly int a can use defaul ...

  9. Navicat(连接) -1之常规设置

    常规设置 要成功地创建一个新的连接到本机或远程服务器 - 不管通过 SSL.SSH 或 HTTP,都要在常规选项卡中设置连接属性.如果你的互联网服务供应商(ISP)不提供直接访问其服务器,安全通道协定 ...

  10. DBA_Oracle Erp加密和解密账户密码(案例)

    2014-09-09 Created By BaoXinjian