本人认为学习jquery反而使本身走了弯路

自定义标签在IE6-8的窘境

2015/07/20 · HTML5 · IE, 自定义标签

原稿出处: 司徒正美   

兴许今后前端组件化之路都以自定义标签,但那东西早在20年前,JSTL已在搞了。以往Web Component还独有webkit扶持。但一个零件库,还索要二个优秀的标记它们是一块的。然而这么些XML已经帮大家化解了,使用scopeName,如”<xxx:dialog>”。在本身继续往下想什么管理怎样为那么些标签绑定数据,与别的零件通讯,管理生命周期,等等大事在此以前,笔者还也许有三个只可以面临的标题,就是什么样宽容IE6-8!

诸如以下七个页面:

图片 1

在chrome, firefox, IE11, IE11的IE6宽容方式分别如下:

图片 2
图片 3
图片 4
图片 5

咱俩会意识IE6下实际是多出广大标签,它是把闭标签也改为一个单身的因金秋点

图片 6

其一AA:DIV标签被开膛破肚,里面子节点全体暴出来,成为其兄弟节点了。因而想包容它,将要费点劲。有个多少个状态供给思考,1是客商已经将它写在页面上,情况同上;2是顾客是将它位于字符串模版中,这么些用正则解决。然而正则假使撞倒复杂的属性名,照旧会晕掉。由此作者如故盘算采取原生的HTML parser。换言之,字符串,小编可能会将它成为节点。这么办吧?!笔者想了相当多主意,后来可能接纳VML的命名空间法解决!

我们将地点的页面改复杂点,再看看效果!

图片 7
图片 8

能够见见其套嵌关系以后完全准确,而且标签字不会大写化,也不会变卦多余节点!

好了,咱们再判别一下是还是不是为自定义标签,也许纯粹地说,那些节点是不是大家组件库中定义的自定义标签。有个别境况下,三个页面能够存在多套组件库,包含avalon的,ploymer的,或然是一向用Web Component写的。

avalon的零部件库将利用命名空间,那样就好界别开。在IE6-9中,推断element.scopeName是或不是为aa(那是组件库的命名空间,你能够改个更宏大上的名字),在其余浏览器推断此因素的localName是或不是以aa:初叶就行了!

JavaScript

function isWidget(el, uiName){ return el.scopeName ? el.scopeName === uiName: el.localName.indexOf(uiName+":") === 0 }

1
2
3
function isWidget(el, uiName){
  return   el.scopeName ? el.scopeName === uiName: el.localName.indexOf(uiName+":") === 0
}

其一难点消除后,大家就足以开断袖之癖于自定义标签的UI库了!

1 赞 1 收藏 评论

图片 9

       还记得小编大二的时候开端接触JS,今年从教室借了N多的图书,然后面看边用editplus写,然后境遇标题,种种DEBUG,在做项指标时候,种种宽容性难题,真是伤心啊。由于品种要求尽快写完,所以就起来接触了jquery,依旧从体育地方抱了几本书,然后下载了jquery源码,然后面看书籍边写代码,看了几章之后,认为貌似简单,然后就从英特网下载了jquery的文书档案,对照着文书档案,对其调用搞获得底相比清楚了。

        未来看来,小编以为学习jquery反而使自个儿走了弯路,用jquery是相比低价,也并不是考虑包容性难题了,何况调用非常轻易华贵,不过,反而小编对原生js感觉尤其面生了,也促成了前边认为完全离不开jquery了,想去写多个XXX组件,想了一晃,思路有了,然后写的时候碰着各类主题材料,然后就又回到jquery了。

         从2018年暑假的时候,笔者说了算离开jquery了,jquery是一把双刃剑,开拓的时候是方便,但是,作为三个初行家,笔者认为那是非常不利于的。

         然后就初阶下载JS的电子书,大概是团结比较躁动吧,看书真心看不进来,小编要么喜欢边看边写代码这种。写了一段时间,逐步的以为最先阶的感觉慢慢回来了,当然,也遇上了N多的标题。

        到寒假的时候,决定自身的毕设不应用今后成熟的JS库,反而自个儿来写贰个不周到的库,那样学习的愈来愈多,当然,也相比较费时间。

        开端写的认为到真是忧伤啊,什么都不懂,所以就去看了看tangram的源码,为何看tangram呢,其实原因比较好笑,那时候校招的时候自个儿面试百度前端,被刷掉了,那时候面试官让自身看看它们百度行使的JS库tangram,小编就想看看它们非常库到底有何样惊天动地的。。。

        写那一个库,首先接纳了命名空间,我比较欣赏toper,所以自个儿首先定义了一个变量:

var tp = tp || {};

        这种艺术也是以人为鉴了tangram的写法,选用对象字面量的样式。那样有着toper定义的主意都献身了tp那么些私有空间内了,比如对DOM的操作就位于tp.dom中。

       由于这一个库完全部都以为毕设做的,所以那之中的点不清文件都感到达成毕设的有个别意义而写的。

      小编利用的结构是core+组件的秘诀,tp.core.js(压缩后为tp.core-min.js),而别的的零部件各个组件三个文本,而组件之间可能存在依附关系,这种倚重关系就因此英特尔化解。

      在未有写那几个库以前,纵然是自己利用jquery,每多个JS文件作者都是向来在HTML文件中使用script标签写进去的,而未来亟需采纳这种异步模块加载的诀窍,假使要动用非大旨模块,那么须要:

tp.use(["tp.a","tp.b"],function(a,b) {

})

      使用use方式,它会自动去下载tp.a.js和tp.b.js,下载完毕未来,施行回调函数。

      同样,在tp.a.js中,也不能运用普通的JS的写法了,而要使用:

 

define("tp.a",["tp.c","tp.d"],function(c,d) {
   tp.modules.add("tp.a",function() {

    });
});

     define的第一个参数是该器件的名字(要求唯一,所以自身或然依据命名空间的办法写的),第贰个参数是这几个组件所依据的组件,第多个参数是回调函数,也正是当正视的零件下载完结今后,回调实践,而tp.modules.add就足以将以此模块加载到整个库中,那样的话手艺应用tp.use调用。

      这种办法本身在tangram中尚无见到,笔者是看了Taobao的KISSY之后求学到的,也正是所谓的AMD(异步模块定义)。

      近些日子AMD的达成方式是通过setInterval,可是将要被重构图片 10

      我前边写了一篇日记来促成英特尔,当然,功效低下,反正大家看看就行了

      然后正是事件了,事件是一个相比恼火的事情,东西相当多,小编把它献身了tp.event这些空间中。

      首先是加上和移除事件监听器,由于IE和非IE采取的措施不雷同,IE采取attach伊夫nt和detechEvent,非IE采取addEventListener和remove伊芙ntListener,并且IE只支持冒泡(从如今因素冒泡到根成分),而非IE扶持冒泡和破获(从根成分捕获到当下因素)。最开始自己是这么做的:

tp.event.on = function(element,event,fn) {
        if (window.attachEvent) {
            //IE
            //第三个参数_realFn是为了修正this
            var realFn = function(e{fn.call(element,e);};
            _realEventCallbackFns[fn] = realFn;
            element.attachEvent("on" + event,realFn);
        } else if (window.addEventListener) {
            element.addEventListener(event, fn,false);
        } else {
            element["on" + event] = fn;
        }
};

     也正是在一个函数内部去看清是还是不是是IE,然后相应的推行相应的函数,可是那样,倘诺加上的风云监听器相当多,每趟都if什么的,作者个人认为很倒霉,所以本人前边增加了二个扶助函数:

var _listeners = {},
        _addEventListener,
        _removeEventListener;
    if (window.attachEvent) {

        var _realEventCallbackFns = {};
        _addEventListener = function(element,event,fn) {
            //第三个参数_realFn是为了修正this
            var realFn = function(e) {fn.call(element,e);};
            _realEventCallbackFns[fn] = realFn;
            element.attachEvent("on" + event,realFn);
        };
        _removeEventListener = function(element,event,fn) {
            element.detachEvent("on" + event,_realEventCallbackFns[fn]);
        };
    } else if (window.addEventListener) {
        _addEventListener = function(element,event,fn,capture) {
            element.addEventListener(event, fn,capture);
        };
        _removeEventListener = function (element,event,fn,capture) {
            element.removeEventListener(event,fn,capture);
        };
    } else {
        _addEventListener = function(element,event,fn) {
            element["on" + event] = fn;
        };
        _removeEventListener = function(element,event) {
            delete element["on" + event];
        };
    }

           那样,整个推断只必要实行三遍,前面调用的时候只必要运用_add伊芙ntListener就能够,当然,由于选择了闭包,tp.event命名空间之外是不行访谈那多少个函数的。

           那那样,tp.event.on就变得极其轻巧了:

tp.event.on = function(element,event,fn) {
        _addEventListener(element,event,fn,false);
         };

          何况这么还应该有三个利润,在此以前的法子只可以动用冒泡方式,但近期,能够动用捕获,当然,只好非IE才干选用,那样在后头使用事件代理一些非冒泡的平地风波的时候特别有用,比方blur和focus事件。

           除了事件监听器,还亟需事件风云的增进,删除等,也等于add,fire,remove等,这里就不说了。

          在行使事件代理的时候,我们平日要拿走到事件的对象成分,而IE和非IE又是分歧样的,所以须求单独写二个函数:

tp.event.getTarget = function(event) {
        return event.target || event.srcElement;
    };

          常用的职能自然照旧阻止事件冒泡以致阻碍私下认可事件的发出,很缺憾,IE和非IE管理方式如故不同的,举例阻止冒泡IE采纳的是cancelBubble,而别的浏览器选择的是stopPropagation,所以依然要求写:

tp.event.preventDefault = function(event) {
        if(event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    };
    tp.event.stopPropagation = function(event) {
        if(event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    };

         事件这一路事实上自个儿做了N多东西,可是出于讲不完,所以有的时候不说了。

        注意一下啊,由于JS变量功能域未有block,所以请不要接纳上面这种:

var arr = new Array();
if(xxx) {
   for(var i = 0,len = arr.length ; i < len; i++) {

   }
} else {
   for(var i = 0,len = arr.length ; i < len; i++) {

   }
}

      那样使用变量i已经被重新定义了,所以须求把变量i定义在if在此之前,即:

var arr = new Array(),
    i;

          事件过后,当然正是DOM了,感觉每一种库在这里个下面都做了许多办事。

         首先是ready的论断,关于那些能够看本身另外一篇日记:

         这里本身注重讲一下tp.dom.query,也正是询问如何是好的,首先拜会常用的询问有:#aa,.aa,input。

         #aa这种比较轻巧,因为JS提供了API,也正是document.getElementById;input这种也相比较好搞,因为JS有document.getElementsByTagName;但是.aa这种艺术就比较郁结了,因为JS没有提供API,幸亏,在一些浏览器中或然提供了API:document.getElementsByClassName,而这几个并未有提供这些API的就相比较喜剧了,只可以遍历全数节点,也正是选用document.getElementsByTagName(*):

          作者此时写了二个支援函数:

var _getElementsByClassName = null;
        if(document.getElementsByClassName) {
                _getElementsByClassName = function(str) {
                    var fetchedEles = document.getElementsByClassName(str),
                        eles = [];

                    for(var i = 0, len = fetchedEles.length; i < len; i++) {
                        eles.push(fetchedEles[i]);
                    }
                    return eles;
                };
        } else {
            _getElementsByClassName = function(str,openClassScan) {
                var eles = [],
                    allElements = document.getElementsByTagName("*"),
                    i;
                if(openClassScan) {
                    for (i = 0; i< allElements.length; i++ ) {
                        if (tp.dom.containClass(allElements[i],str)) {
                            eles.push(allElements[i]);
                        }
                    }
                } else {
                    for (i = 0; i< allElements.length; i++ ) {
                        if (str === allElements[i].className) {
                            eles.push(allElements[i]);
                        }
                    }
                }
                return eles;
            };
        }

            小编那儿写了一个openClassScan参数,解释一下,那一个参数是为了消除类似于<div class = "a b"></div>这种,因为假如要帮衬通过API查询如class:a,那么须要各样节点都认清是还是不是contain那么些class,比较费时间,而自个儿以为非常多时候不须要,所以暗许自身关闭了。

            PS:使用了原生的document.getElementsByClassName的肯定不受那么些影响的。

           作者把每七个查询如:tp.dom.query("#aa input")分为二种,一种为轻松询问(也便是如查询:#aaa),别的一种是纵横交错查询,每一种复杂查询都是由众多简便询问构成的,比如#aaa input,就足以切成:#aaa和input。

           所以,在种种查询的最起先,需求将传递的查询格式化,举例#aa >input这种格式化为:#aa > input,几个空格变为1个空格,>两侧必需有一个空格等。

           之后写多少个扶持函数,判别是还是不是是复杂查询,要是是,那么切开查询字符串,切成数组。

           我认为:#aa input这种实际上尽管经过document.getElementById查询之后然后查询它的子孙节点中的全部满意tagName为input的成分;而#aaa > input这种就是询问它的男女节点中是否有这种满足条件的因素。以后全部流程相比轻易了,对于二个错落有致查询,首先进行叁个简便询问,然后根据查询的结果集合,进行一回遍历,对每种节点查询它的子女节点或子孙节点,将装有知足条件的放入到别的贰个数组,假设该数组为空,那么直接重临空数组,不然,继续张开下叁回询问(照旧查询孩子节点或子孙节点)。

           小编以为,就这么二个效应比较轻便的query就够了,不须要达成类似于jquery里面包车型大巴这么繁复的询问,如果要使用它,其实也很简短,因为jquery的查询引擎sizzle已经开源,完全能够将它参预到那么些库,而现行反革命toper也是那样做的,要调用sizzle就应用:

tp.use("tp.dom.sizzle",function(sizzle) {});

          感到JS的宽容性真心异常高烧啊,就举个例子在DOM这一道,为了合作,小编都做了很短日子。当然,DOM这一路必然不仅如此一点内容,一时半刻也不写了。

          除了DOM,对变量类型的决断和浏览器的检查评定也是很要紧的。

         首先,类型决断,由于JS是弱类型语言,而不常候是内需判别它的品类的,当然也能够运用typeof 去看清,暂且小编是如此做的:

  

tp.type = tp.type || {};
tp.type.isArray = function(ele) {
    return "[object Array]" === Object.prototype.toString.call(ele);
};
tp.type.isFunction = function(ele) {
    return "[object Function]" === Object.prototype.toString.call(ele);
};
tp.type.isObject = function(ele) {
    return ("function" === typeof ele) || !!(ele && "object" === typeof ele);
};
tp.type.isString = function(ele) {
    return "[object String]" === Object.prototype.toString.call(ele);
};
tp.type.isNumber = function(ele) {
    return "[object Number]" === Object.prototype.toString.call(ele) && isFinite(ele);
};
tp.type.isBoolean = function(ele) {
    return "boolean" === typeof ele;
};
tp.type.isElement = function(ele) {
    return ele && ele.nodeType == 1;
};
tp.type.isUndefined = function(ele) {
    return "undefined" === typeof ele;
};

        小编看了一晃,分裂的库的剖断方式不平等,作者此刻使用的是tangram的论断方式。

        然后正是浏览器推断,笔者是如此写的:

(function() {
    var ua = navigator.userAgent;
    tp.browser.isIe = ua.hasString("MSIE") && !ua.hasString("Opera");
    tp.browser.isFirefox = ua.hasString("Firefox");
    tp.browser.isChrome = ua.hasString("Chrome");
    tp.browser.isWebKit = ua.hasString("WebKit");
    tp.browser.isGecko = ua.hasString("Gecko") && !ua.hasString("like Gecko");
    tp.browser.isOpera = ua.hasString("Opera");
    tp.browser.isSafari = ua.hasString("Safari") && !ua.hasString('Chrome');
    tp.browser.isStrict = ("CSS1Compat" === document.compatMode);
})();

       当然,还只怕有浏览器版本的判断,临时就不贴出来了。这里基本思路就是判断navigator.useAgent重回的字符串中,各样浏览器里面包车型客车这些字符串是不一致的,当然,这几个进度比较恶心,并且有望后面某三个浏览器会更改它的userAgent,导致整个推断失效,比如IE,听人家说后边新IE要把userAgent搞成firefox,真心搞不懂,那是要逆天啊?

       除了这种判定格局,还足以由此判断是不是有某三个函数或某四个变量来决断,这种判定方式自个儿记不清叫什么名字了,反正在此以前这种叫浏览器嗅探。

       除了代码之外,工具也很关键,另一篇日记介绍JS工具的:

        对动画片有意思味的童鞋,能够看看自家的近年求学JS的感悟-2,关于动画的。

       行吗,貌似又超时了,先就这么呢,以为每趟写这种日志都会开销不知凡几时间。

本文由金莎娱乐场官方网站发布于关于计算机,转载请注明出处:本人认为学习jquery反而使本身走了弯路

TAG标签:
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。