• 【写一个自己的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

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

  • 相关阅读:
    Java -- Map
    Bootstrap -- 标签属性
    SQLServer -- 竟然默认不区分大小写
    ThinkPHP -- 问题
    ThinkPHP
    MVC-内容详情页显示内容
    未能加载文件或程序集“Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed”或它的某一个依赖项。
    Random.Next获取随即数
    Razor语法小记
    VisualStudio自定义代码段_方法二
  • 原文地址:https://www.cnblogs.com/pandabunny/p/4748692.html
Copyright © 2020-2023  润新知