【写一个自己的js库】 1.搭个架子先

   最近在看《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;

})()
View Code

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

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

   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;
    }
View Code

   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;
    }
View Code

   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;
    }
View Code

   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;
    }
View Code

  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;
    }
View Code

  8.insertAfter在referenceNode后插入元素。

function insertAfter(node, referenceNode){
        if(!(node = $(node))) return false;
        if(!(referenceNode = $(node))) return false;

        return referenceNode.parentNode.insertBefore(node, referenceNode.nextSibling);
    }
View Code

  9.removeChildren删除所以子节点。

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

  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;
    }
View Code

   现在一个简单的框架就搭完了,用下面的代码测试一下啊。以下是改写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>
View Code

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

posted @ 2015-08-21 18:24  lily white  阅读(309)  评论(0编辑  收藏  举报