在javascript - 工作笔记 (事件绑定二)篇中,我将事件的方法做了简单的包装,

 JavaScript Code 
1
2
3
4
5
 
yx.bind(item, "click", function (e) {
        //console.log("Div Click 1 !");
        alert("Div Click 1 !");
        e.stopPropagation();
    });

  但是这样用起来有些不顺手,添加方法还要加个标签元素对象,能不能去掉第一个参数呢,答案是肯定的。

我们只需要将DOM元素对象转换成Yx对象,就可以了。但是要如何将dom变成Yx对象呢,如下:

 JavaScript Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
var Yx = function (ele) {//dom元素对象
    var self = this;
    if (
    (ele instanceof Array) ||
    (NodeList || (ele instanceof NodeList))) {
        ; i < ele.length; i++) {
            self[i] = ele[i];
        }
        self.length = ele.length;
    } else {
        self[] = ele;
        self.length = ;
    }
    return self;
}

  我们将dom元素对象挂在Yx对象的下面,像数组一样,使用下标获取,设置值,同时还保留了DOM节点自带的方法,属性。这时,我们使用的时候如下:

 JavaScript Code 
1
2
3
 
var item = document.getElementById("test");//获取dom对象
var yxItem = new Yx(item);//新建Yx对象
yxItem.bind( "click", function (e) { ... });//绑定事件

  但,这样写也有点不爽,每次还要new一下,能省掉new吗,当然可以。

 JavaScript Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 
Yx.prototype.init = function(ele){
    var self = this;
    if(
    (ele instanceof Array) ||
    (NodeList || (ele instanceof NodeList))){
        ;i<ele.length;i++){
            self[i] = ele[i];
        }
        self.length = ele.length;
    }else{
        self[] = ele;
        self.length = ;
    }
    return self;
}

  我们新建一个方法为init用来新建Yx对象使用,同时,我们在构造方法中,这样写:

 JavaScript Code 
1
2
3
4
5
6
7
8
 
var Yx = function(ele){

Yx.fn = Yx.prototype;//将Yx原型链赋值给Yx.fn
    Yx.fn.init.prototype = Yx.fn;//实际是将Yx的原型链赋值给Yx.fn.init,这样Yx.fn.init就具有与Yx一样的原型链,
    
    return new Yx.fn.init(ele);//在这里实例化的是Yx.fn对象,但是它具有有Yx一样的原型链,
    //new 出来的对象与Yx对象是相同的
}

//这种方法因为在使用的时候去掉了new,被称为无new的构造方法,在源码中,我介绍了两种无new方法,写法不同,其实原理一样。

这时候我们使用方法如下:

 JavaScript Code 
1
2
3
4
5
6
7
8
9
 
var item = document.getElementById("test");  
var yxItem = yx(item);//直接调用yx方法,该方法中new Yx.fn对象
yxItem.bind("click",function(e){
    console.log("Div Click 1 !");
    e.stopPropagation();
});

window.$ = window.yx = Yx;//当然得有这么一句话才能直接使用yx(...)方法了,

完整代码如下:

 JavaScript Code 
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 
(function (window) {

var Yx = function (ele) {

//第一种无new实现方法
        var a = Yx.prototype; //将Yx.prototype存入a变量中,这样a变量中就含有了init这个方法,应该叫做对象
        //在javascript中任何事物都是对象,函数也是对象,xxx()是执行函数,new xxx()则是新建对象了,
        a.init.prototype = a; //将a(即:Yx.prototype原形链赋值给a.init对象的原形链,使这两个对象具有相同的方法,属性)
        return new a.init(ele); //新建一个a.init对象,该对象与new Yx(else)的对象具有相同的方法,属性

//第二种无new实现方法

//Yx.fn = Yx.prototype;
        //Yx.fn.init.prototype = Yx.fn;
        //return new Yx.fn.init(ele);
    }
    Yx.evGuid = ;
    window.NodeList = function () { } || window.NodeList;//IE下午NodeList对象
    //初始化
    Yx.prototype.init = function (ele) {
        var self = this;
        if (
    (ele instanceof Array) ||
    (NodeList && (ele instanceof NodeList))) {
            ; i < ele.length; i++) {
                self[i] = ele[i];
            }
            self.length = ele.length;
        } else {
            self[] = ele;
            self.length = ;
        }
        return self;
    }
    Yx.prototype.bind = function (evName, evFunc) {
        var self = this;
        ; i < self.length; i++) {
            self.bindEv(self[i], evName, evFunc);
        }
    }
    Yx.prototype.unbind = function (evName, evFunc) {
        var self = this;
        ; i < self.length; i++) {
            self.unbindEv(self[i], evName, evFunc);
        }
    }
    //绑定事件
    Yx.prototype.bindEv = function (ele, evName, evFunc) {
        if (!evFunc.$$guid) evFunc.$$guid = Yx.evGuid++; //为新添加的事件添加标识
        if (!ele.events) ele.events = {}; //为元素添加事件集合
        evName = evName;
        if (!ele.events[evName]) {
            ele.events[evName] = {};
        }
        if (ele.events[evName][evFunc.$$guid] == undefined)
            ele.events[evName][evFunc.$$guid] = {};
        ele.events[evName][evFunc.$$guid] = evFunc;
        ele["on" + evName] = eventManager; //事件统一处理
    }
    //解绑事件
    Yx.prototype.unbindEv = function (ele, evName, evFunc) {
        if (ele.events && ele.events[evName]) {
            delete ele.events[evName][evFunc.$$guid];
        }
    }
    //事件管理
    function eventManager(e) {
        var self = this; //当前对象
        var e = e || window.event; //event对象
        if (!e.stopPropagation) {//IE下的阻止默认行为,事件冒泡
            e.preventDefault = function () { this.returnValue = false; }
            e.stopPropagation = function () { this.cancelBubble = true; }
        }
        var evFuncs = self.events[e.type]; //获取当前对象,指定的事件名称事件数组
        for (var key in evFuncs) {
            evFuncs[key](e, self);
        }
    }
    window.$ = window.yx = Yx;//将Yx方法给两个别名
})(window);

var test = document.getElementById("test");
var testItem = yx(test);

testItem.bind("click", function (e) {
    //console.log("Div Click 1 !");
    alert("Div Click 1 !");
    e.stopPropagation();
});

var funcTest1 = function (e) {
    //console.log("Div Click 2 !");
    alert("Div Click 2 !");
};

testItem.bind("click", funcTest1);

var pArr = document.getElementsByTagName("p");
var pArrItem = $(pArr);

pArrItem.bind("click", function (e, item) {
    //console.log(item.innerHTML);
    alert(item.innerHTML);
    e.preventDefault();
});

var link = document.getElementById("a_link");
var linkItem = $(link);
linkItem.bind("click", function (e, item) {
    //console.log(item.innerHTML);
    alert(item.innerHTML);
    e.preventDefault();
});

  第一种无new方法与第二种无new方法原理一样,只是第一种方法看的明白些,第二种看起来NB一些,哈哈!

  Demo请点这里

javascript - 工作笔记 (事件四)的更多相关文章

  1. How Javascript works (Javascript工作原理) (十四) 解析,语法抽象树及最小化解析时间的 5 条小技巧

    个人总结:读完这篇文章需要15分钟,文章介绍了抽象语法树与js引擎解析这些语法树的过程,提到了懒解析——即转换为AST的过程中不直接进入函数体解析,当这个函数体需要执行的时候才进行相应转换.(因为有的 ...

  2. javascript - 工作笔记 (事件绑定)

    背景: 目前所做的项目,只能使用的是原生的javascript.对于javascript的事件绑定想必大家都懂得语法: 1,在标签中使用属性调用方法:<div onclick="AAA ...

  3. javascript - 工作笔记 (事件绑定二)

    在上篇中的事件绑定方法,相信大家都看到过了. 不过这里有点小小的问题,这些方法,变量都是全局的,难免会与其他的库或者方法发生冲突而被覆盖,因此,我在这里做了小小的封装,如下:  JavaScript ...

  4. javascript - 工作笔记 (事件三)

    有关定义就不多说了,事件分两种 一,冒泡型事件 这是IE浏览器中事件模型的实现,顾名思义,就像水中的泡一样,自底而上,其经过的父元素都会触发对应的事件. 即:触发元素的父元素先于触发元素触发,看dem ...

  5. JavaScript学习笔记——事件

    javascript事件基础和事件绑定 一.事件驱动 1.事件 javascript侦测到的用户的操作或是页面的一些行为(怎么发生的) 2.事件源 引发事件的元素.(发生在谁的身上)3.事件处理程序 ...

  6. javascript学习笔记(四):事件处理函数和动态创建html标记。

    1 HTML的事件属性  全局事件属性:HTML 4 增加了使事件在浏览器中触发动作的能力,比如当用户点击元素时启动 JavaScript. a. Window 事件属性,针对 window 对象触发 ...

  7. JavaScript基础笔记(四) JS式面向对象

    JS式面向对象 一.理解对象 一)属性类型 ECMA-262 第 5 版在定义只有内部才用的特性(attribute)时,描述了属性(property)的各种特征. ECMA-262 定义这些特性是为 ...

  8. 8. JavaScript学习笔记——事件

    8. 事件 8.1 事件基础 /// 事件就是用户或浏览器自身执行的某种动作.诸如 click.load 和 mouseover,都是事件的名字.而响应某个事件的函数就叫做事件处理程序(或事件侦听器) ...

  9. iOS工作笔记(十四)

    1.scrollview的frame指的是其可视范围,contentSize指的是其滚动范围,分别是在水平方向和竖直方向上的 所以要让scrollview在水平方向不能滚动,那么需要如下设置 _scr ...

随机推荐

  1. Hello又大了一岁

    时间就这样子过了一年一年一年一年一年...一年一年一年......... 以往每年的生日,都习惯安静的猫在一个地方.时间流逝,更像是一种默默的悼念. 也许从28岁开始,我得习惯用逗比的心态欢迎.长大的 ...

  2. U盘开发之SSD对比

    U盘因其小巧方便,逐步取代了笨重的移动硬盘和光驱,成为最普及的存储介质.现在的主板BIOS也将支持USB启动,作为标准之一,再过几年,光驱时代可能就要终结了.从早期的16MU盘,到现在动辄几个G,U盘 ...

  3. "NO 3D support is available from the host"

    https://forums.opensuse.org/showthread.php/494522-No-3d-Support-or-graphics-accelleration http://ask ...

  4. linux的NetworkManager服务(转)

    在开启NetworkManager服务的情况下,在终端下敲“service network restart”命令: 正在关闭接口 eth0: 设备状态:3 (断开连接) [确定] 正在关闭接口 eth ...

  5. linux之SQL语句简明教程---函数

    既然数据库中有许多资料都是已数字的型态存在,一个很重要的用途就是要能够对这些数字做一些运算,例如将它们总合起来,或是找出它们的平均值.SQL 有提供一些这一类的函数.它们是: AVG (平均) COU ...

  6. hdu 4627 The Unsolvable Problem(暴力的搜索)

    Problem Description There are many unsolvable problem in the world.It could be about one or about ze ...

  7. magento url rewrite

    Magento 设置 Rewrite Url 方法. 1.apache 要加载 Rewrite 扩展模块.2.网站根目录要有 .htaccess 文件.3.Magento 后台要设置启用 Rewrit ...

  8. Zepto 使用中的一些注意点

    Zepto 只针对移动端浏览器编写,因此体积更小.效率更高,更重要的是,它的 API 完全仿照 jQuery ,所以学习成本也很低. 但是在开发过程中,我发现 Zepto 还远未成熟,其中包含了一些或 ...

  9. 自定义按照index和key访问的List

    List<T>用起来比较方便,但是有时候要按照Index来访问List中的对象有些繁琐,所以想是不是扩展一下,既能按照Index来访问,又能按照Key访问. 实现方法: public cl ...

  10. C#运算符的优先级

    在C#中,一共有38个常用的运用符,根据它们所执行运算的特点和它们的优先级,为了便于记忆,我将它们归为七个等级:1.单元运算符和括号.2.常规算术运算符.3.位移运算符.4.比较运算符.5.逻辑运算符 ...