最近在看《javascript dom 高级程序设计》,想着跟着里面的代码敲一遍吧,也算是做一下学习笔记吧,所以这不是重新发明轮子,只是个学习的过程。

1.先确定自己的命名空间,并且加入几个常用的js方法。命名空间很重要啊,保证了自己库里的变量不污染全局空间,不和其他的库的变量名起冲突。命名空间的惯例就是把代码都放在自执行函数(function(){})()里了,然后暴露个方法给window对象了。所以0.1版本的代码就长下面这样了。(这里暂时没有用继承)

(function(){
//命名空间
var Lily = {}
if(!window.Lily){
window['Lily'] = Lily
} function isCompatible(other){}
Lily['isCompatible'] = isCompatible; function $(){}
Lily['$'] = $; function addEvent(node, type, listener){}
Lily['addEvent'] = addEvent; function removeEvent(node, type, listener){}
Lily['removeEvent'] = removeEvent; function getElementsByClassName(className, tag, parent){}
Lily['getElementsByClassName'] = getElementsByClassName; function toggleDisplay(node, value){}
Lily['toggleDisplay'] = toggleDisplay; function insertAfter(node, referenceNode){}
Lily['insertAfter'] = insertAfter; function removeChildren(parent){}
Lily['removeChildren'] = removeChildren; function prependChild(parent, newChild){}
Lily['prependChild'] = prependChild; })()

2.开始填充方法了。isCompatible是看浏览器是否能与这个库兼容,这里用能力检测来看浏览器是否能支持库中所使用的方法。

function isCompatible(other){
if(other === false
|| !Array.prototype.push
|| !Object.hasOwnProperty
|| !document.createElment
|| !document.getElementsByTagName
){
return false;
}
return true;
}

3.$是查找dom对象的方法,这个要比jquery的$方法简单许多,只支持代表id的字符串或字符串数组,或者dom对象。支持dom对象是方便库中的方法,当参数为字符串或者dom都可以用$转成dom对象。

function $(){
var elements = new Array(); for(var i = 0; i < arguments.length; i++){
var element = arguments[i]; if(typeof element == "string"){
element = document.getElementById(element);
} if(arguments.length == 1){
return element;
}
elements.push(element);
} return elements;
}

4.addEvent是支持跨浏览器必须实现的一个方法,ie的事件绑定方法是attachEvent,并且它的方法参数中没有event对象,所以手动将window.event传入到listener中。之前有点困惑为什么没有用匿名函数绑定,查了下用匿名函数的话,就无法解除绑定了。ie6,7,8中用attachEvent绑定的事件中,this指向的是window,所以用node.call修正了this的指向问题。addEventListener的第三个参数指是否使用捕获,默认值是false,而且ie6,7,8中只支持冒泡,所以一般都用false。关于addEvent有个更周全的版本就是Dean Edwards的,jquery中也参考了他的很多方法,目前为了保持简单,先用这个,以后可能会替换成Dean Edwards版本的。

function addEvent(node, type, listener){
if(!isCompatible()) return false;
if(!(node = $(node))) return false; if(node.addEventListener){
node.addEventListener(type, listener, false);
return true;
}else if(node.attachEvent){
node[type + listener] = function(){
listener.call(node, window.event);
};
node.attachEvent('on'+type, node[type + listener]);
return true;
}
return false;
}

5.removeEvent就没什么好说的了,就是detach之后,别忘了把node[type + listener]释放掉。

function removeEvent(node, type, listener){
if(!(node = $(node))) return false;
if(node.removeEventListener){
node.removeEventListener(type, listener, false);
return true;
}else if(node.detachEvent){
node.detachEvent('on'+type, node[type + listener]);
node[type + listener] = null;
return true;
}
return false;
}

6.getElementsByClassName根据class选择dom对象,后两个参数可以不传。parent.all貌似是解决ie5的bug吧,没有细研究,总之满足条件就用document.all吧。正则表达式(^|\\s+)匹配起始位置或者空格。

function getElementsByClassName(className, tag, parent){
var elements = new Array();
parent = parent || document;
tag = tag || "*";
if(!(parent = $(parent))) return false; var allTags = (tag == "*" && parent.all) ? parent.all : parent.getElementsByTagName(tag);
className = className.replace(/\-/g, "\\-");
var regexp = new RegExp("(^|\\s+)" + className + "(\\s+|$)"); for(var i = 0; i < allTags.length; i++){
var element = allTags[i];
if(regexp.test(element.className)){
elements.push(element);
}
} return elements;
}

7.toggleDisplay第二个参数也可以不传,但是当元素的display不是空值时(比如display:inline-block),可以传入第二个参数,这样在切换时就保留了原来的值。

function toggleDisplay(node, value){
if(!(node = $(node))) return false; if(node.style.display != "none"){
node.style.display = "none"
}else{
node.style.display = value || '';
} return true;
}

8.insertAfter在referenceNode后插入元素。

function insertAfter(node, referenceNode){
if(!(node = $(node))) return false;
if(!(referenceNode = $(node))) return false; return referenceNode.parentNode.insertBefore(node, referenceNode.nextSibling);
}

9.removeChildren删除所以子节点。

function removeChildren(parent){
if(!(parent = $(parent))) return false;
while(parent.firstChild){
parent.firstChild.parentNode.removeChild(parent.firstChild);
}
return parent;
}

10.prependChild将子节点加入到父节点中的第一个。

function prependChild(parent, newChild){
if(!(parent = $(parent))) return false;
if(!(newChild = $(newChild))) return false; if(parent.firstChild){
parent.insertBefore(newChild, parent.firstChild);
}else{
parent.appendChild(newChild);
} return parent;
}

现在一个简单的框架就搭完了,用下面的代码测试一下啊。以下是改写a标签的默认事件,用弹出事件代替跳转事件。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="Lily-0.1.js" type="text/javascript"></script>
<script type="text/javascript">
Lily.addEvent(window, "load", function(){
var aTags = Lily.getElementsByClassName("popup");
for(var i = 0 ; i < aTags.length; i++){
Lily.addEvent(aTags[i], "click", function(){
alert(this.href);
return false;
});
}
});
</script>
</head>
<body>
<ul>
<li><a href="hello.html" class="popup">hello</a></li>
<li><a href="hello.html" class="popup">hello</a></li>
<li><a href="hello.html" class="popup">hello</a></li>
</ul>
</body>
</html>

还未进行浏览器兼容性测试,如有问题,请指正,谢谢~

【写一个自己的js库】 1.搭个架子先的更多相关文章

  1. 【写一个自己的js库】 2.实现自己的调试日志

    还是本着学习的目的,实现一个自己的调试日志,界面很简单,就是将调试信息显示在页面的正中央,用一个ul包裹,每条信息就是一个li. 1.新建一个myLogger.js文件,将需要的方法声明一下.其中va ...

  2. 【写一个自己的js库】 5.添加修改样式的方法

    1.根据id或class或tag修改样式,样式名是-连接格式的. function setStyleById(elem, styles){ if(!(elem = $(elem)) return fa ...

  3. 【写一个自己的js库】 3.添加几个处理字符串的方法

    1.生成重复的字符串 if(!String.repeat){ String.prototype.repeat = function (count){ return new Array(count + ...

  4. 【写一个自己的js库】 4.完善跨浏览器事件操作

    1.阻止冒泡. function stopPropagation(event){ event = event || getEvent(event); if(event.stopPropagation) ...

  5. 仿照jquery封装一个自己的js库(二)

    本篇为完结篇.主要讲述如何造出轮子的高级特性. 一. css方法的高级操作 先看本文第一部分所讲的dQuery css方法 //css方法 dQuery.prototype.css=function( ...

  6. 仿照jquery封装一个自己的js库(一)

    所谓造轮子的好处就是复习知识点,加深对原版jquery的理解. 本文系笔者学习jquery的笔记,记述一个名为"dQuery"的初级版和缩水版jquery库的实现.主要涉及知识点包 ...

  7. 仿照jquery封装一个自己的js库

    所谓造轮子的好处就是复习知识点,加深对原版jquery的理解.本文系笔者学习jquery的笔记,记述一个名为"dQuery"的初级版和缩水版jquery库的实现.主要涉及知识点包括 ...

  8. 自己动手写一个iOS 网络请求库的三部曲[转]

    代码示例:https://github.com/johnlui/Swift-On-iOS/blob/master/BuildYourHTTPRequestLibrary 开源项目:Pitaya,适合大 ...

  9. 如何写一个自定义的js文件

    自定义一个Utils.js文件,在其中写js代码即可.如: (function(w){ function Utils(){} Utils.prototype.getChilds = function( ...

随机推荐

  1. Oracle监控指标

    1.数据文件或数据设备 参考:http://f.dataguru.cn/thread-106901-1-1.html2.数据库日志空间活或回滚段(包括大小.设备.文件及可用率.日志空间竞争情况或回滚段 ...

  2. 强化一下,QDialog有专门的exec函数和finished信号,QWidget都没有

    http://blog.csdn.net/dbzhang800/article/details/6300519

  3. 可以供MFC调用的,QT实现的DLL(qtwinmigrate实现)

    MFC和QT的消息循环机制不同,所以,要让QT写的DLL可以供MFC调用,要做一点特殊的处理 #include <qmfcapp.h> #include <qwinwidget.h& ...

  4. MFC子窗口和父窗口(SetParent,SetOwner)

    一.概念和区别 在windows系统中,每个窗口对象都对应有一个数据结构,形成一个list链表.系统的窗口管理器通过这个list来获取窗口信息和管理每个窗口.这个数据结构中有四个数据用来构建list, ...

  5. [Leetcode][Python]43: Multiply Strings

    # -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com' 43: Multiply Stringshttps://leetcode.co ...

  6. 构造函时和this指针

    通常this指针在对象构造完毕后才完全生成,而在构造函数执行过程中,对象还没有完全生成,所以this指针也是没有完全生成的,在构造函数中使用this指针会存在问题,应该尽量避免. 构造函数中可以访问对 ...

  7. 浅谈JNDI的使用

    原文:http://www.weicoop.com/web/article/52.html 关于什么是JNDI的概念这里不做解释,本文作为初学者根据所了解到内容做些总结,主要内容如下: 1.JNDI使 ...

  8. MVC3.0修改jquery.validate.unobtrusive.js实现气泡提示mvc错误

    CSS部分 <style type="text/css"> .hide {display:none;} .poptip { position: absolute; to ...

  9. POJ 1734 求最小环路径 拓展Floyd

    九野的博客,转载请注明出处:http://blog.csdn.net/acmmmm/article/details/11888019 题意: n个点 m条无向边 下面m条有权无向边 问图中最小环的路径 ...

  10. 关于smali插桩

    虽说是老生常谈的东西了,稍微记录一下. 我觉得最重要的就是寄存器的问题了,如果需要额外的寄存器,要在smali函数的最前面将寄存器数量增加到需要的数量. 在smali代码中,寄存器有两种表示方式,一种 ...