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

})()

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>

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

时间: 2024-08-06 17:46:14

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

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

还是本着学习的目的,实现一个自己的调试日志,界面很简单,就是将调试信息显示在页面的正中央,用一个ul包裹,每条信息就是一个li. 1.新建一个myLogger.js文件,将需要的方法声明一下.其中var声明的是私有成员,可见范围只在构造函数中,每个实例都会保存一套他们的副本.this声明的是特权方法,new的时候会把它绑定到实例上,实例可以直接调用它.在prototype上声明的就是公有方法了,每个实例都可以访问它.最后将一个实例赋值给Lily这个库,Lily就有自己的日志插件了. functi

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

1.生成重复的字符串 if(!String.repeat){ String.prototype.repeat = function (count){ return new Array(count + 1).join(this); } } 2.去除开头和结尾的空字符 if(!String.trim){ String.prototype.trim = function (){ return this.replace(/^\s+|\s+$/g, ''); } } 3.将"-"格式的字符串变成

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

1.根据id或class或tag修改样式,样式名是-连接格式的. function setStyleById(elem, styles){ if(!(elem = $(elem)) return false; for(prop in styles){ if(!styles.hasOwnProperty(prop)) continue; if(elem.style.setProperty){ elem.style.setProperty(prop, styles[prop]); }else{ el

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

1.阻止冒泡. function stopPropagation(event){ event = event || getEvent(event); if(event.stopPropagation){ event.stopPropagation(); }else{ event.cancelBubble = true; } } Lily['event'] = stopPropagation; 2.阻止事件默认动作. function preventDefault(event){ event =

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

代码示例:https://github.com/johnlui/Swift-On-iOS/blob/master/BuildYourHTTPRequestLibrary 开源项目:Pitaya,适合大文件上传的 HTTP 请求库:https://github.com/johnlui/Pitaya 本系列文章中,我们将尝试使用 NSURLSession 技术构建一个自己的网络请求库. NSURLSession 简介 NSURLSession 是 iOS7 引入的新网络请求接口,在 WWDC2013

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

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

isMobile 一个简单的JS库,用来检测移动设备

github地址: https://github.com/kaimallea/isMobile 示例 (function () { var MOBILE_SITE = 'http://m.xx.com/index.html', NO_REDIRECT = 'noredirect'; if (isMobile.any) { if ( document.cookie.indexOf(NO_REDIRECT) === -1 ) { document.location = MOBILE_SITE; }

近期写js库中遇到的一个判别的问题

最近在写一个自己的js库,正写到数组包,在里面定义了一个排序,只对纯数字数据进行排序的方法,但是在测试的时候发现一个很诡异的问题,那就是传入一个对象的时候,它没有返回erroemsg而是返回了对象,上代码: 1 array.sort=function(a){//only for num 2 try{ 3 4 if(!a.some(function(x){return(typeof("string"))})){ 5 var max=a.length-1; 6 7 for(var j=0;

【转载】写一个js库需要怎样的知识储备和技术程度?

作者:小爝链接:https://www.zhihu.com/question/30274750/answer/118846177来源:知乎著作权归作者所有,转载请联系作者获得授权. 1,如何编写健壮的javascript代码,鲁棒性,简单总结几条我觉得是常识的事:1.1 一个javascript库最好的实现方式是占用最少的命名空间,比如window对象上或者global对象上只占用一个引用.1.2 健壮的js程序对输入都会有完善的类型检查和异常处理,边界值的判断.1.3 对js的几种继承方式要足