JavaScript实现自定义对象的自定义事件

前言:

大家都知道,在使用JavaScript可以很方便的使用addEventListener函数给DOM对象快速绑定一个或多个事件侦听器。

我们又如何在JavaScript的自定义对象中使用此方法并触发事件呢?这就是本章节的核心内容了。

目的:

现在有一个需求,要求“a对象”能够让“b对象“做一系列动作。

分析后我们得知。首先,”b对象“有一个固定名称作为入口让a对象调用,并且这个入口可以自动检索所有符合这个动作要求的函数并依次触发。

实现:

好的,经过以上内容我们可以简单的了解到为什么我们需要自定义事件了。

接下来我们来用代码具体实现一下。

function CursomObject (table) {
    /// <summary>这是一个自定义对象类型</summary>
    /// <param name="table" type="Object" optional="true">要添加的函数及属性表</param>

    // 这里要存放我们的自定义事件
    // 因为是一个表,所以我们使用Object类型
    this._events = {};

    // 得到函数及属性表中的内容
    for (var i in table) this[i] = table[i];
}

上面这段代码定义了一个CursomObject类型,这将作为下面所做操作的基础。

CursomObject.prototype.addEventListener = function (type, listener, capture) {
    /// <summary>添加事件侦听器</summary>
    /// <param name="type" type="String">事件类型</param>
    /// <param name="listener" type="Function">触发的函数</param>
    /// <param name="capture" type="Boolean" optional="true">是否在捕获阶段触发(这里只是做了顺序排列)</param>

    // 判断一下传入的参数是否符合规格
    if (typeof type !== "string" || typeof listener !== "function") return this;

    // 缓存符合条件的事件列表
    var list = this._events[type];

    // 判断是否已经有该类型事件,若没有则添加一个新数组
    if (typeof list === "undefined") list = (this._events[type] = []);

    /* 判断插入函数的位置 */
    if (!!capture) list.push(listener);
    else list.insert(0, listener);

    return this;
};

至此,我们已经实现了一个简单的事件监听器的添加功能了。

这里需要注意一下,list.insert中的insert函数在JavaScript的Array中是不存在的,我们将在下面的扩展函数中找到。

另外,return this; 则是为了方便链式编程【详情请参阅”附录1“】

CursomObject.prototype.removeEventListener = function (type, listener, capture) {
    /// <summary>移除事件侦听器</summary>
    /// <param name="type" type="String">事件名称</param>
    /// <param name="listener" type="Function">触发的函数</param>
    /// <param name="capture" type="Boolean">是否在捕获阶段触发</param>

    // 判断一下传入的参数是否符合规格
    if (typeof type !== "string" || typeof listener !== "function") return this;

    // 缓存符合条件的事件列表
    var list = this._events[type];

    // 若没有绑定过此类事件则不需要做处理
    if (typeof list === "undefined") return this;

    for (var i = 0, len = list.length; i < len; i++) {
        // 通过循环判断来确定事件列表中存在要移除的事件侦听函数
        if (list[i] == listener) {
            // 找到后将此侦听函数从事件列表中移除
            list.remove(i);
            break;
        }
    }
    return this;
};

以上过程简单明了,一个循环搞定问题。

同时这个也需要注意,JavaScript中的Array中是不存在remove函数的,同样在下面扩展函数中会出现。

CursomObject.prototype.fireEvent = function (type, e) {
    /// <summary>触发事件</summary>
    /// <param name="type" type="String">事件名称</param>
    /// <param name="e" type="Object">附加参数对象</param>

    // 若存在DOM0用法的函数,则触发
    this["on" + type.toLowerCase()] && this["on" + type.toLowerCase()].call(this, e);

    // 缓存符合条件的事件列表
    var list = this._events[type];

    // 若事件列表中没有内容则不需要做处理
    if (!list || list.length <= 0) return this;

    // 阻止事件冒泡开关
    var isStop = false;

    // 模拟事件对象
    window.event = { stopPropagation: function () { isStop = true; } };
    e.stopPropagation = window.event.stopPropagation;

    for (var i = 0, len = list.length; i < len; i++) {
        // 通过循环触发符条件的事件列表中存在的所有事件侦听函数
        // 若函数内返回false或事件内调用了event.stopPropagation函数则阻止接下来的所有调用
        if (list[i].call(this, e) === false || isStop) break;
    }
    return this;
};

注释已经说的很清楚了,这里就不再累述。

那么至此就主体就已经完成了。下面放出扩展函数。

Array.prototype.insert = function (index, value) {
    /// <summary>插入项</summary>
    /// <param name="index" type="Number">索引</param>
    /// <param name="value" type="Object">元素</param>
    /// <returns type="Array" />

    if (index > this.length) index = this.length;
    if (index < -this.length) index = 0;
    if (index < 0) index = this.length + index;
    for (var i = this.length; i > index; i--) {
        this[i] = this[i - 1];
    }
    this[index] = value;
    return this;
};

Array.prototype.remove = function (index) {
    /// <summary>移除项</summary>
    /// <param name="index" type="Number">索引</param>
    /// <returns type="Array" />

    if (isNaN(index) || index > this.length) return;
    this.splice(index, 1);
};

OK,已经全部完成了。

下面放出完整代码。

function CursomObject(table) {
    /// <summary>这是一个自定义对象类型</summary>
    /// <param name="table" type="Object" optional="true">要添加的函数及属性表</param>

    // 这里要存放我们的自定义事件
    // 因为是一个表,所以我们使用Object类型
    this._events = {};

    // 得到函数及属性表中的内容
    for (var i in table) this[i] = table[i];
}

CursomObject.prototype.addEventListener = function (type, listener, capture) {
    /// <summary>添加事件侦听器</summary>
    /// <param name="type" type="String">事件类型</param>
    /// <param name="listener" type="Function">触发的函数</param>
    /// <param name="capture" type="Boolean" optional="true">是否在捕获阶段触发(这里只是做了顺序排列)</param>

    // 判断一下传入的参数是否符合规格
    if (typeof type !== "string" || typeof listener !== "function") return;

    // 缓存符合条件的事件列表
    var list = this._events[type];

    // 判断是否已经有该类型事件,若没有则添加一个新数组
    if (typeof list === "undefined") list = (this._events[type] = []);

    /* 判断插入函数的位置 */
    if (!!capture) list.push(listener);
    else list.insert(0, listener);

    return this;
};

CursomObject.prototype.removeEventListener = function (type, listener, capture) {
    /// <summary>移除事件侦听器</summary>
    /// <param name="type" type="String">事件名称</param>
    /// <param name="listener" type="Function">触发的函数</param>
    /// <param name="capture" type="Boolean">是否在捕获阶段触发</param>

    // 判断一下传入的参数是否符合规格
    if (typeof type !== "string" || typeof listener !== "function") return this;

    // 缓存符合条件的事件列表
    var list = this._events[type];

    // 若没有绑定过此类事件则不需要做处理
    if (typeof list === "undefined") return this;

    for (var i = 0, len = list.length; i < len; i++) {
        // 通过循环判断来确定事件列表中存在要移除的事件侦听函数
        if (list[i] == listener) {
            // 找到后将此侦听函数从事件列表中移除
            list.remove(i);
            break;
        }
    }
    return this;
};

CursomObject.prototype.fireEvent = function (type, e) {
    /// <summary>触发事件</summary>
    /// <param name="type" type="String">事件名称</param>
    /// <param name="e" type="Object">附加参数对象</param>

    // 若存在DOM0用法的函数,则触发
    this["on" + type.toLowerCase()] && this["on" + type.toLowerCase()].call(this, e);

    // 缓存符合条件的事件列表
    var list = this._events[type];

    // 若事件列表中没有内容则不需要做处理
    if (!list || list.length <= 0) return this;

    // 阻止事件冒泡开关
    var isStop = false;

    // 模拟事件对象
    window.event = { stopPropagation: function () { isStop = true; } };
    e.stopPropagation = window.event.stopPropagation;

    for (var i = 0, len = list.length; i < len; i++) {
        // 通过循环触发符条件的事件列表中存在的所有事件侦听函数
        // 若函数内返回false或事件内调用了event.stopPropagation函数则阻止接下来的所有调用
        if (list[i].call(this, e) === false || isStop) break;
    }
    return this;
};

Array.prototype.insert = function (index, value) {
    /// <summary>插入项</summary>
    /// <param name="index" type="Number">索引</param>
    /// <param name="value" type="Object">元素</param>
    /// <returns type="Array" />

    if (index > this.length) index = this.length;
    if (index < -this.length) index = 0;
    if (index < 0) index = this.length + index;
    for (var i = this.length; i > index; i--) {
        this[i] = this[i - 1];
    }
    this[index] = value;
    return this;
};

Array.prototype.remove = function (index) {
    /// <summary>移除项</summary>
    /// <param name="index" type="Number">索引</param>
    /// <returns type="Array" />

    if (isNaN(index) || index > this.length) return;
    this.splice(index, 1);
};

使用:

上面已经详述了自定义事件的具体实现。

接下来我们就可以使用了,那么怎么使用呢?

function Test() {
    /// <summary>这是一个自定义类型</summary>

    // 继承CursomObject中的属性
    CursomObject.apply(this);
}
// 继承CursomObject中的函数
Test.prototype = new CursomObject();

// 定义一个从Test类型中派生出来的对象
var a = new Test();

// 绑定一个message事件的侦听器
a.addEventListener("message", function (e) {
    alert(e);
}, false);

// 再绑定一个message事件的侦听器
a.addEventListener("message", function (e) {
    alert("内容:" + e);
}, false);

// 触发message事件
a.fireEvent("message", "这是参数……");

至此结束。

如果疑问请留言,我将及时回复。

谢谢您的观看!

时间: 2024-11-07 05:06:42

JavaScript实现自定义对象的自定义事件的相关文章

TreeSet排序,存储自定义对象,自定义比较器示例

Set:无序,不可以重复元素. |--HashSet:数据结构是哈希表.线程是非同步的. 保证元素唯一性的原理:判断元素的hashCode值是否相同. 如果相同,还会继续判断元素的equals方法,是否为true. |--TreeSet:可以对Set集合中的元素进行排序. 底层数据结构是二叉树. 保证元素唯一性的依据:compareTo方法return 0. TreeSet排序的第一种方式:让元素自身具备比较性. 元素需要实现Comparable接口,覆盖compareTo方法. 也种方式也成为

JavaScript 阻止DOM对象的所有事件

event.stopImmediatePropagation(); 使用此方法可阻止该DOM对象的所有事件执行!案例 onclick="return setIds(event)" function setIds(event){ if (!confirm('xxxxx')){ event.stopImmediatePropagetion(); return false; } return true; }

javascript中Document对象的常用事件

1.onabort事件:对象载入被中断时触发 2.onblur事件:元素或窗口本身失去焦点时触发. 3.onchange事件:改变<select>元素中的选项或者其他表单元素失去焦点,并且在其获取焦点后内容发生过改变时触发. 4.onclick事件:单机鼠标左键时候触发.当光变的焦点在按钮上,并且按下Enter键时,也会触发该事件. 5.onblclick事件:双击鼠标左键时候触发. 6.onerror事件:出现错误时候触发. 7.onfocus事件:任何元素或者窗口本身获得焦点时触发. 8.

iOS 自定义对象及子类及模型套模型的拷贝、归档存储的通用代码

一.runtime实现通用copy 如果自定义类的子类,模型套模型你真的会copy吗,小心有坑. copy需要自定义类继承NSCopying协议 #import <objc/runtime.h> - (id)copyWithZone:(NSZone *)zone { id obj = [[[self class] allocWithZone:zone] init]; Class class = [self class]; while (class != [NSObject class]) {

JavaScript内置对象(一)

一.什么是对象     1.什么是对象:JavaScript中的所有事物都是对象:字符串.数值.数组.函数... 每个对象带有属性和方法 JavaScript允许自定义对象 2.自定义对象: 定义并创建对象实例 使用函数来定义对象,然后创建新的对象实例 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head>

Node.js自定义对象事件监听与发射

一.Node.js是以事件驱动的,那我们自定义的一些js对象就需要能监听事件以及发射事件.在Node.js中事件使用一个EventEmitter对象发出,该对象在events模块中.它应该是使用观察者设计模式来实现把事件监听器添加到对象以及移除,之前写OC那块的时候也有些观察者设计模式,在OC中也经常用到:通知中心.KVO,也很容易理解. .addListener(eventName,callback):将回调函数附加到对象的监听器中.当eventName的事件被触发时,回调函数被放置在事件队列

javascript 学习之自定义滚动条加滚轮事件

要自己写一个自定义滚动条加上滚轮事件,之前的没有滚轮事件不完整,今天整理了一个. 1.滚轮事件是不兼容的,firefox中是必需要用事件绑定的添加,用的DOMMouseScroll,当滚动鼠标的时候,只要鼠标滚动的方法就行了,而这通过检测datail的正负号就可以确定 2.其他的用mousewheel(Ie是onmousewheel),通过检测wheelDelta 1 <!doctype html> 2 <html> 3 <head> 4 <title>拖拽

JavaScript学习-自定义对象/

JavaScript学习 [自定义对象] 1.基本概念 ① 对象概念: 对象是包含一系列无序属性和方法的集合: ② 对象中的数据,是以键值对形式存在的,以键取值: ③ 属性:描述对象特征的一系列变量.[对象中的变量]: ④ 方法:描述对象行为的一系列方法.[对象中的函数]: 2.对象的声明: ① 字面量声明: var ovj={ key1:value1, //属性 key2:value2 func:function(){} //方法 } ② 对象中的键,可以是任何数据类型.但,一般用作普通变量名

JavaScript 类的定义和引用 JavaScript高级培训 自定义对象

在Java语言中,我们可以定义自己的类,并根据这些类创建对象来使用,在Javascript中,我们也可以定义自己的类,例如定义User类.Hashtable类等等. 一,概述 在Java语言中,我们可以定义自己的类,并根据这些类创建对象来使用,在Javascript中,我们也可以定义自己的类,例如定义User类.Hashtable类等等. 目前在Javascript中,已经存在一些标准的类,例如Date.Array.RegExp.String.Math.Number等等,这为我们编程提供了许多方