最近在看《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. windows查询端口

    依次点击“开始→运行”,键入“cmd”并回车,打开命令提示符窗口.在命令提示符状态下键入“netstat -an”,按下回车键后就可以看到以数字形式显示的TCP和UDP连接的端口号及状态.

  2. Android Fragment(碎片)的使用

    简介 在Android中Fragment为一种可以嵌入活动中的UI片段.能让程序更加合理地利用大屏幕的空间. 使用方法 1.我们首先新建的一个onefragment.xml文件. <?xml v ...

  3. Python中yield深入理解

    众所周知,python中的yield有这样的用法: def test(alist): for i in alist: yield i 这样,这个test函数就变成了一个生成器,当每次调用的时候,就会自 ...

  4. nginx模块开发获取post参数

    > 您好!>     我想请问下nginx模块里面怎么获取post参数,能有具体的代码更好!谢谢> 对于 "application/x-www-form-urlencode ...

  5. Android之SurfaceView学习

    首先我们先来看下官方API对SurfaceView的介绍 SurfaceView的API介绍 Provides a dedicated drawing surface embedded inside ...

  6. Thinking in C++: 第1章 为什么C++会成功(改进了C的缺点,可复用C的知识与库,执行效率相当)

    本文内容摘抄自C++经典书籍:<Thinking in C++>   操作概念:OOP程序像什么 我们已经知道,用C 语言编写的过程程序就是一些数据定义和函数调用.要理解这种程序的含义,程 ...

  7. DEP受保护的问题(尤其是Outlook)

    We see this issue quite regularly as we use MAPI and lots of our users run our application on TS. Of ...

  8. zookeeper数据弱一致性

    zookeeper本身支持单机部署和集群部署,生产环境建议使用集群部署,因为集群部署不存在单点故障问题,并且zookeeper建议部署的节点个数为奇数个,只有超过一半的机器不可用整个zk集群才不可用. ...

  9. 蜂鸟A20开发板刷 cubietruck 的 SD 卡固件

    美睿视讯 为蜂鸟A20准备的 MerriiLinux 功能非常简陋.所以能用上主流的 debian 或者 LUbuntu 就可以说是非常迫切的需求了.蜂鸟A20(Merrii Hummingbird ...

  10. Geoserver基本使用、WMS服务发布与OpenLayers测试

    1.Geoserver与OpenLayers的下载 Geoserver:http://geoserver.org/ OpenLayers:http://openlayers.org/ 2.安装部署Ge ...