如今学习JS的醒悟www.301.net:,JavaScript高级程序设计

自定义标签在IE六-8的困境

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

原稿出处:
司徒正美   

只怕今后前端组件化之路都是自定义标签,但那东西早在20年前,JSTL已在搞了。未来Web
Component还只有webkit协理。但三个组件库,还索要三个非正规的标识它们是一块的。但是这一个XML已经帮大家解决了,使用scopeName,如”<xxx:dialog>”。在本身连续往下想什么处理怎样为这些标签绑定数据,与其余零件通讯,管理生命周期,等等大事从前,作者还有一个不得不面对的题材,正是怎么着包容IE陆-8!

譬如以下3个页面:

www.301.net 1

在chrome, firefox, IE11, IE1一的IE陆包容形式分别如下:

www.301.net 2
www.301.net 3
www.301.net 4
www.301.net 5

咱俩会发现IE6下实际是多出累累标签,它是把闭标签也改为二个单身的因九秋点

www.301.net 6

其1AA:DIV标签被开膛破肚,里面子节点全部暴出来,成为其兄弟节点了。因而想包容它,就要费点劲。有个三个情景供给思考,一是用户已经将它写在页面上,意况同上;二是用户是将它坐落字符串模版中,那么些用正则消除。可是正则若是碰撞复杂的属性名,照旧会晕掉。由此笔者依然打算动用原生的HTML
parser。换言之,字符串,笔者要么会将它成为节点。这么办呢?!作者想了过多办法,后来还是利用VML的命名空间法消除!

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

www.301.net 7
www.301.net 8

能够看看其套嵌关系今后完全正确,并且标签名不会大写化,也不会转变多余节点!

好了,我们再判定一下是或不是为自定义标签,或然纯粹地说,这些节点是否我们组件库中定义的自定义标签。有些景况下,二个页面可以存在多套组件库,包涵avalon的,ploymer的,或然是直接用Web
Component写的。

avalon的机件库将利用命名空间,那样就好界别开。在IE6-玖中,判定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 收藏
评论

www.301.net 9

     
 还记得作者大二的时候开首接触JS,那年从教室借了N多的书籍,然后面看边用editplus写,然后蒙受难题,各类DEBUG,在做项目标时候,种种包容性难点,真是伤心啊。由于类别要求尽快写完,所以就起来接触了jquery,依旧从体育场面抱了几本书,然后下载了jquery源码,然前面看书籍边写代码,看了几章之后,觉得貌似简单,然后就从网上下载了jquery的文书档案,对照着文书档案,对其调用搞获得底相比较清楚了。

第11章, DOM扩展

       
今后看来,小编以为学习jquery反而使本身走了弯路,用jquery是相比便宜,也休想思量包容性难题了,而且调用卓殊简单优雅,可是,反而小编对原生js感觉越来越不熟悉了,也导致了后头感觉完全离不开jquery了,想去写1个XXX组件,想了一下,思路有了,然后写的时候遭遇种种题材,然后就又回到jquery了。

选择符 API

Selector API
Level1
主旨措施querySelector 、querySelectorAll,包容的浏览器能够选拔 Document,Element 实例调用它们,支持浏览器:IE捌+,Firefox3.5+,Safari三.一+,chrome,Opera十+

       
 从2018年暑假的时候,小编说了算离开jquery了,jquery是一把双刃剑,开发的时候是造福,可是,作为三个初学者,作者以为那是很不利的。

querySelector方法

接到2个 CSS选用符,再次来到与该形式相配的率先个要素

经过 Document类型调用该函数,会在文书档案范围查找相配成分,通过 Element类型调用该函数,只会在该因素后代范围内寻找

注:传入不被帮助的选项符会抛出荒唐

例:

//取得body 元素
var body = document.querySelector(“body”);
//取得ID 为”myDiv”的元素
var myDiv = document.querySelector(“#myDiv”);
//取得类为”selected” 的第一个元素
var selected = document.querySelector(“.selected”);
//取得类为”button” 的第一个图像元素
var img = document.querySelector(“img.button”);

       
 然后就开端下载JS的电子书,大概是团结相比躁动吧,看书真心看不进去,作者要么喜欢边看边写代码这种。写了壹段时间,慢慢的以为最开首的感觉到稳步回来了,当然,也碰到了N多的题材。

querySelectorAll方法

与querySelector接收一样的参数,不过回到的是三个NodeList实例,具体点就是,再次回到的值实际上是带有全部属性和办法的 NodeList。

与querySelector类似,能够调用querySelectorAll的品类蕴含Document、DocumentFragment、Element

例:

//取得某<div>中所有<em>元素(类似getElementsByTagName("em"))
var ems = document.getElementById("myDiv").querySelectorAll("em");
//取得类为"selected"的所有元素
var selecteds = document.querySelectorAll(".selectored");
//取得所有<p>元素中的所有<strong>元素
var strongs = document.querySelectorAll("p strong");

要获取再次来到的NodeList的因素,可以应用item方法或方括号法

注:传入不被协理的精选符会抛出荒唐

Selector API
Level2
专业为Element类型新增了2个格局matchesSelector,接收2个参数,CSS选取符,若调用成分与该选拔符相配重回true,不然重回false

注:到201壹年年中还未有浏览器协助此方法,但是,IE玖+通过msMatchesSelector,Firefox3.陆+通过mozMatchesSelector,Safari伍+和Chrome通过webkitMatchesSelector扶助该措施

       
到寒假的时候,决定自身的毕设不选择未来成熟的JS库,反而本身来写多个不周详的库,那样学习的越来越多,当然,也相比较费时间。

装进该方式代码:

function matchesSelector(element,selecrot){
     if(element.matchesSelector){
          return element.matchesSelector(selector);
     }else if(element.msMatchesSelector){
          return element.msMatchesSelector(selector);
     }else if(element.mozMatchesSelector){
          return element.mozMatchesSelector(selector);
     }else if(element.webkitMatchesSelector){
          return element.webkitMatchesSelector(selector);
     }else {
          throw new Error("Not supported");
     }
}
if(matchesSelector(document.body,"body.page1")){
     //操作
}

       
开端写的感到真是痛楚啊,什么都不懂,所以就去看了看tangram的源码,为何看tangram呢,其实原因相比搞笑,当时校招的时候自身面试百度前端,被刷掉了,当时面试官让自家看看它们百度应用的JS库tangram,作者就想看看它们分外库到底有如何惊天动地的。。。

要素遍历

对此成分间空格,IE玖及在此之前并不会回去文本节点,别的浏览器都会,为此Element
Traversal规范新定义属性:

childElementCount:重返子成分个数,不包涵文件节点和注释

firstElementChild:firstChild元素版

lastElementChild:lastChild元素版

previousElementSibling:previousSibling元素版

nextElementSibling:nextSibling元素版

利用上述因素得以无需顾虑空白文本节点

帮衬Element Traversal规范的浏览器IE9+,Firefox3.5+,Safari肆+,Chrome和Opera10+

       
写那几个库,首先使用了命名空间,小编相比欣赏toper,所以作者先是定义了三个变量:

HTML5

H伍新增了广大API,致力于简化CSS类的用法

var tp = tp || {};

1、getElementsByClassName方法

document及拥有HTML成分都能够调用该办法

此格局接收3个参数,包括2个或多少个类名的字符串,再次来到带有钦赐类的富有因素结合的NodeList

//取得所有类中包含"username"和"current"的元素,类名先后顺序无关
var allCurrentUsernames = document.getElementsByClassName("username current");
//取得ID为"myDiv"的元素中所有类名"selected"的所有元素
var selected = document.getElementById("myDiv").getElementsByClassName("selected");

在要素上调用,只会回来后代成分中的相配,在document上调用,重回全体

注:因为重临的是NodeList,所以,会设有与富有重返NodeList的不二等秘书籍同样的习性难点

支撑的浏览器IE九+,Safari3.一+,Firefox叁+,Chrome,Opera玖.5+

       
这种格局也是以史为鉴了tangram的写法,接纳对象字面量的方式。那样有着toper定义的格局都置身了tp那个私有空间内了,比如对DOM的操作就坐落tp.dom中。

2、classList属性

H五为具备因素添加了classList属性,是新集合类型DOMTokenList的实例。DOMTokenList有length属性,能够由此item方法和方括号法访问元素,此外定义的艺术:

add(value):将加以的字符串值添加到列表中,已存在不添加

contains(value):列表是或不是留存给定值,是,重临true,否,重返false

remove(value):移除给定字符串

toggle(value):列表若已存在,移除,不设有,添加

例:

<div class="bd user disabled">..</div>
//删除"disabled"类
div.classList.remove("disabled");
//切换"user"类
div.classList.toggle("user");

     
 由于这些库完全是为毕设做的,所以这其间的多多文本都是为贯彻毕设的一点效能而写的。

主旨管理

document.activeElement属性,始终获得当前DOM获得了关子的要素,元素得到主旨形式:页面加载,用户输入(常常通过tab),代码中调整focus方法。

文书档案刚加载完,document.activeElement保存document.body,加载时期为null

document。hasFocus方法,鲜明文书档案是或不是收获核心

兑现那两本性情浏览器IE四+,Firefox三+,Safari四+,Chrome,Opera8+

     
小编利用的组织是core+组件的格局,tp.core.js(压缩后为tp.core-min.js),而任何的零部件各类组件贰个文件,而组件之间或然存在依靠关系,那种依赖关系就透过AMD化解。

H5扩展了HTMLDocument

     
在未曾写那个库在此以前,即便是本身动用jquery,每一个JS文件笔者都是一向在HTML文件中利用script标签写进去的,而现行反革命需求选择那种异步模块加载的法子,假设要使用非大旨模块,那么须求:

1、readyState属性

值:loading –>
正在加载,complete –> 加载完毕

支撑的浏览器IE四+,Firefox叁.陆+,Safari,Chrome,Opera九+

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

})

2、包容方式

     
使用use方式,它会自行去下载tp.a.js和tp.b.js,下载达成之后,执行回调函数。

3、head属性

H5新增document.head属性,得到<head>成分,辅助浏览器Chrome,Safari5+

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

字符集属性

H伍新增charset属性,表示文书档案实际运用字符集,可更改,帮忙浏览器IE,Safari,Chrome,Opera。Firefox援救Characterset

defaultCharset属性,表示根据暗许浏览器和操作系统设置,分明用吗字符集,扶助浏览器IE,Safari,Chrome

能够自定义非标准属性,要添加前缀data-,dataset属性能够访问,dataset是DOMStringMap的实例

 

插入标记

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

    });
});

1、innerHTML属性

读方式,重临与调用元素的全部子节点对应的HTML标记,包括属性,注释,文本节点

写模式,依照内定值创设DOM树,然后用这几个DOM树替换原先全部子节点

注:设置的HTML字符串,会透过分析

注:限制:在大部分浏览器中通过此属性插入<script>元素并不会进行在那之中的剧本,IE八及更早版本能够,条件还挺多

不协理此属性的要素:<col>,<colgroup>,<frameset>,<head>,<html>,<style>,<table>,<tbody>,<thead>,<tfoot>,<tr>,在IE八及更早浏览器<title>也从未

   
 define的率先个参数是该零件的名字(供给唯1,所以本身要么遵照命名空间的章程写的),第一个参数是其1组件所依靠的零部件,第陆个参数是回调函数,也便是当注重的机件下载达成未来,回调执行,而tp.modules.add就足以将以此模块加载到一切库中,那样的话才能选拔tp.use调用。

2、outerHTML属性

读方式,再次来到与调用成分的全部子节点对应的HTML标记

写情势,依照钦命值创立DOM树,然后用这几个DOM树替换原先成分

支撑的浏览器IE四+,Safari4+,Chrome,Opera八+。Firefox7及以前版本都不帮助

     
那种方法本身在tangram中从不观看,小编是看了Tmall的KISSY之后上学到的,也正是所谓的AMD(异步模块定义)。

3、insertAdjacentHTML方法

接受多个参数:要插入的职务,要插入的HTML文本,第多少个参数必须是下列值之壹

“beforebegin”,在方今因素此前插入紧邻的同辈成分

“afterbegin”,在当下因素插入多个新的子元素或在首先个子成分在此以前插入新的子成分

“beforeend”,在近日因素以下插入1个新的子成分或在最后一个子成分之后插入新的子成分

“afterend”,在脚下成分之后插入二个同辈成分

     
权且英特尔的完结情势是通过setInterval,可是即将被重构www.301.net 10

4、内存品质难题

动用上述的艺术或许引致浏览器内部存款和储蓄器占用难题。调用方法是,最棒手工业删除被交流来分的有着事件处理程序

注:尽量裁减innerHTML和outerHTML的次数,压缩使用

例:

for(var i = 0, len = values.length;i < len; i++){
     ul.innerHTML += "<li>"+values[i] +"</li>";          //要访问两次innerHTML,一次读,一次写,渣渣的性能
}
//改进版本:
var item = "";
for(var i = 0, len = values.length;i < len; i++){
     item += "<li>"+values[i] +"</li>";                  //构建HTML字符串
}
ul.innerHTML = item;                                     //只进行一次调用,一定程度上提高了性能
document.documentMode;                                   //返回给定页面使用的文档模式的版本号

contains方法:接收多个参数,要检测的节点,再次回到调用此方法的节点是还是不是含有检查实验节点

支撑的浏览器IE,Safari,Firefox九+,Chrome,Opera。

DOM Level 三compareDocumentPosition方法也能够规定节点间关系,协理浏览器IE9+,Safari,Firefox,Chrome,Opera九.伍+。重返用于表示五个节点间的涉嫌的位掩码

掩码

节点关系

1

无关,给定节点不在当前文档中

2

居前

4

居后

8

包含

16

被包含

     
作者前边写了壹篇日记来完毕英特尔,当然,成效低下,反正大家看看就行了

安排文本

尚未纳入H5规范的习性

     
然后正是事件了,事件是三个比较恼火的工作,东西相比多,作者把它坐落了tp.event这些空间中。

1、innerText

<div id="content">
     <p>This is a <strong>paragraph</strong> with a list following it.</p>
     <ul>
          <li>Item 1</li>
          <li>Item 2</li>
          <li>Item 3</li>
     </ul>
</div>

对<div>成分而言innerText再次来到:(不肯定带有原始代码的缩进)

This is a paragraph with a list following it. 

Item 1 

Item 2 

Item 3

使用innerText设置:

div.innerText = "hello world!";

结果:

<div id="content">hello world!</div>

注:innerText也会对文本中的HTML语法字符(>,<,”,&)举行编码

帮衬的浏览器IE四+,Safari三+,Chrome,Opera8+。Firefox不协理,但协助类似属性textContent属性,textContent是DOM
Level 叁规定的贰本性能,IE九+,Safari3+,Chrome,Opera拾+也协助textContent

     
首先是加上和移除事件监听器,由于IE和非IE选取的主意不等同,IE选拔attach伊芙nt和detech伊芙nt,非IE选取add伊芙ntListener和remove伊芙ntListener,而且IE只援救冒泡(从脚下因素冒泡到根成分),而非IE辅助冒泡和破获(从根成分捕获到当下元素)。最初叶自身是那样做的:

2、outerText

除此之外功用范围扩展到了包括调用它的节点之外,outerText与innerText基本相同

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

第12章,DOM2和DOM3

DOM1级重要定义HTML和XML文书档案底层结构。DOM二和DOM三则在此基础引入越来越多互动能力,协理更加高级的XML天性。

   
 也正是在3个函数内部去看清是不是是IE,然后相应的实践相应的函数,可是这么,假设加上的风云监听器很多,每一回都if什么的,小编个人感觉很不佳,所以笔者背后添加了二个推来推去函数:

DOM2级:

着力:在1级基础上,为节点添加越来越多措施和个性

视图:为文书档案定义了基于样式音讯的分化视图

事件:表达了什么样行使事件与DOM文书档案交互

体制:定义了什么以编制程序方式来拜访和改变CSS样式音讯

遍历和界定:引进了遍历DOM文书档案和挑选其特定部分的新接口

HTML:在壹级基础上,添加更加多属性,方法和新接口

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];
        };
    }

检验浏览器是还是不是支持DOM模块:

var supportsDOM2Core = document.implementation.hasFeature("Core","2.0");
var supportsDOM3Core = document.implementation.hasFeature("Core","3.0");
var supportsDOM2HTML = document.implementation.hasFeature("HTML","2.0");
var supportsDOM2Views = document.implementation.hasFeature("Views","2.0");
var supportsDOM2XML = document.implementation.hasFeature("XML","2.0");

         
 那样,整个判定只须要举办3遍,前面调用的时候只要求运用_add伊芙ntListener即可,当然,由于接纳了闭包,tp.event命名空间之外是不行访问那多少个函数的。

本着XML命名空间变化

<!-- 不加前缀:-->
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Example XHTML page</title>
    </head>
    <body>
        Hello World!
    </body>
</html>
<!-- 加前缀:-->
<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml">
    <xhtml:head>
        <xhtml:title>Example XHTML page</xhtml:title>
    </xhtml:head>
    <xhtml:body>
        Hello World!
    </xhtml:body>
</xhtml:html>

错落使用二种语言,命名空间用途才能够反映

DOM二级大旨为大多数DOM一级方法提供一定于命名空间的本子消除难点

           那那样,tp.event.on就变得分外简单了:

一、Node类型变化

在DOM2级,包罗下列特定于命名空间的品质

localName:不带命名空间前缀的节点名称

namespaceUHummerH贰I:命名空间UWranglerI或(未钦命意况下)null

prefix:命名空间前缀或(未钦点情形)null

当节点使用了命名空间前缀时,nodeName等于prefix+”:”+localName,如下:

<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>Example XHTML page</title>
    </head>
    <body>
        <s:svg xmlns:s="http://www.w3.org/2000/svg" version="1.1"
            viewBox="0 0 100 100" style="width:100%; height:100%">
            <s:rect x="0" y="0" width="100" height="100" style="fill:red"/>
        </s:svg>
    </body>
</html>

<html>:localName和tagName=”html”,namespaceURI=”

<s:svg>:localName=”svg”,tagName=”s:svg”,namespaceURI=””

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

DOM三级在此基础再引进:

isDefaultNamespace(namespaceULX570I),钦赐的namespaceU君越I是不是是当前节点的暗许命名空间

lookupNamespaceUQashqaiI(prefix),再次回到给定的prefix的命名空间

lookupPrefix(namespaceU福特ExplorerI),再次来到给定的namespaceULX570I的前缀

         
而且这么还有3个便宜,此前的办法只好选用冒泡情势,但方今,能够应用捕获,当然,只好非IE才能采取,那样在前面使用事件代理1些非冒泡的轩然大波的时候特别有用,比如blur和focus事件。

二、Document类型变化

带有下列与命名空间有关的法子:

createElementNS(namespaceULX570I,tagName):使用给定的tagName创造一个属于命名空间namespaceUGL450I的新因素

createAttributeNS(namespaceU宝马X叁I,attributeName):使用给定的attributeName创设三个属于命名空间namespaceUENCOREI的新特色

getElementsByTagNameNS(namespaceU索罗德I,tagName):再次来到属于命名空间namespaceULANDI的tagName成分的NodeList

例:

//创建一个新的svg元素
var svg = document.createElementNS("http://www.w3.org/2000/svg","svg");
//创建一个属于某个命名空间的新特性
var att = document.createAttributeNS("http://www.somewhere.com","random");
//取得所有XHTML元素
var elems = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml","*");

注:唯有在文书档案中留存多少个命名空间的时候,这么些与命名空间有关的措施展才能是必备的

         
 除了事件监听器,还必要事件风浪的增加,删除等,也便是add,fire,remove等,那里就不说了。

叁、Element类型变化

要害涉及操作性格,新增方法如下

getAttributeNS(namespaceU兰德酷路泽I,localName):取得属于命名空间namespaceUCRUISERI且名字为localName的特点

getAttributeNodeNS(namespaceURI,localName):取节点

getElementsByTagNameNS(namespaceU陆风X8I,tagName):重回属于命名空间的tagName元素的NodeList

hasAttributeNS(namespaceUQashqaiI,localName):分明当前因素是还是不是有1个名称为localName的特色,而且该本性的命名空间是namespaceU智跑I。注意:DOM二基本,也扩大3个hasAttribute方法,用于不思量命名空间的状态

removeAttributeNS(namespaceU哈弗I,localName):删除特性

setAttributeNS(namespaceUPAJEROI,qualifiedName,value):设置属于命名空间且名称为qualifiedName的性状值为value

setAttributeNodeNS(attNode):设置属于命名空间的特色节点

注:除第3个参数外,那么些格局与DOM一级相关措施效果1样

         
在应用事件代理的时候,大家平时要拿到到事件的目的成分,而IE和非IE又是不一致的,所以须要独自写贰个函数:

四、NamedNodeMap类型变化

增加产量方法多数景观只针对特征应用

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

别的变化

         
常用的机能自然依然阻止事件冒泡以及阻碍暗中认可事件的爆发,很遗憾,IE和非IE处理情势照旧区别的,比如阻止冒泡IE采取的是cancelBubble,而任何浏览器选用的是stopPropagation,所以仍旧供给写:

1、DocumentType类型

增加产量属性:publicId,systemId,internalSubset,前多个象征文书档案类型注明中的新闻段,在DOM第11中学不也许访问

使用:document.doctype.publicId

internalSubset用于访问文书档案类型申明中的额外定义

不怕没啥用的说

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

2、Document类型

转变中绝无仅有与命名空间非亲非故的艺术:importNode(),用途:从3个文书档案中获得2个节点,将其导入到另1个文书档案

注:各个节点都有3个ownerDocument属性,使用appendChild时传出的节点属于分裂文书档案,则会出错,importNode则不会

与Element的cloneNode方法丰富相像,接收四个参数,要复制的节点,是不是复制子节点的布尔值

DOM二级视图添加defaultView属性,指向拥有给定文档的窗口,除IE外,都帮忙,IE帮助等价属性:parentWindow

DOM二级宗旨为document.implementation对象分明五个新办法:createDocumentType(成立新的DocumentType节点,接收四个参数:文书档案类型名称,publicId,systemId),creteDocument(接收八个参数:针对文书档案元素的namespaceU福特ExplorerI,文书档案成分标签名,新文书档案的文书档案类型)

DOM②级HTML为document.implementation新增方法createHTMLDocument,接收二个参数:新创设的文书档案的标题,唯有Opera和Safari协助

       
 事件那壹块儿实际本身做了N多东西,然则出于讲不完,所以一时不说了。

3、Node类型

唯1叁个与命名空间非亲非故变化,isSupported方法用于明显当前节点有所啥能力,接收多少个参数:天性名,版本号,存在于hasFeature相同的标题

提议:最佳照旧利用力量检查测试明确有些天性是还是不是可用

DOM3级:isSameNode和isEqualNode,接收3个节点参数

isSameNode是或不是同3个目标,指向的是同一个对象

isEqualNode是不是一律体系,具有10分属性(相同地方,相同值)

例:

var div1 = document.createElement("div");
div1.setAttribute("class","box");
var div2 = document.createElement("div");
div2.setAttribute("class","box");
alert(div1.isSameNode(div1));   //true
alert(div1.isEqualNode(div2));  //true
alert(div1.isSameNode(div2));   //false

DOM三级:setUserData,接收二个参数:要安装的键,实际数目,处理函数

getUserData传入相同的键能够获取数据

处理函数接收四个参数:操作类型(一复制,二导入,三去除,4重命名),数据键,数据值,源节点,目的节点

        注意一下哟,由于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++) {

   }
}

样式

概念样式格局:<link/>包蕴外部文件,<style/>定义嵌入样式,style性子定义针对一定成分样式

//确定浏览器是否支持DOM2级定义CSS能力
var supportsDOM2CSS = document.implementation.hasFeature("CSS","2.0");
var supportsDOM2CSS2 = document.implementation.hasFeature("CSS2","2.0");

style本性中钦点的别的CSS属性都将呈现为那些style对象的品质,对于利用短划线(background-image)的CSS属性,必须变换为驼峰大小写方式

注:float为js保留字,无法由此轻重写转换,DOM二级样式规定,对应对象属性名应是cssFloat,Firefox,Safari,Opera,Chrome都帮助,IE援救styleFloat

      那样使用变量i已经被再度定义了,所以必要把变量i定义在if此前,即:

1、DOM样式属性和方式:

cssText:访问style性子中的CSS代码

length:CSS属性数量

parentRule:CSS信息的CSSRule对象

getPropertyCssValue(propertyName):重返给定属性值的CSSValue对象

getPropertyPriority(propertyName):若给定的性质使用了!important设置,重回important,不然,重返空串

getPropertyValue(propertyName):重回给定属性的字符串值

item(index):重临给定地方的CSS属性名称

removeProperty(propertyName):从体制中删除给定属性

setProperty(propertyName,value,priority):将给定属性设置为对应的值,并累加优先权标志(important或3个空荡荡)

var arr = new Array(),
    i;

操作样式表

CSSStyleSheet类型表示的是样式表,CSSStyleSheet对象是一套只读接口,CSSStyleSheet继承自StyleSheet

利用于文书档案的全数样式表通过document.styleSheets集合来代表,通过length能够了然样式表数量,通过方括号法和item方法能够访问每1个样式表

          事件今后,当然就是DOM了,感觉每种库在那个方面都做了许多工作。

1、CSS规则

CSSRule对象表示样式表中每一条规则,实际上是三个供其余几种类型继承的基类型,常见的是CSSStyleRule类型

       
 首先是ready的论断,关于那么些能够看本人别的壹篇日记:

二、成立规则

动用insertRule方法,接收三个参数:规则文本,在什么地方插入规则的目录

支撑浏览器:Firefox,Safari,Opera,Chrome。IE八及更早版本支持类似措施addRule,接收四个必选参数:选拔符文本和CSS样式音讯,2个可选参数:插入规则位置

提出:选择以前介绍过的动态加载样式表的技巧

       
 那里作者根本讲一下tp.dom.query,也等于查询如何是好的,首先看望常用的询问有:#aa,.aa,input。

叁、删除规则:慎用

deleteRule接收3个参数:要刨除的平整的职位

       
 #aa这种比较简单,因为JS提供了API,也正是document.getElementById;input那种也正如好搞,因为JS有document.getElementsByTagName;不过.aa这种办法就比较纠结了,因为JS没有提供API,幸亏,在局地浏览器中照旧提供了API:document.getElementsByClassName,而那么些尚未提供那一个API的就比较正剧了,只好遍历全体节点,也正是使用document.getElementsByTagName(*):

遍历

DOM二级遍历和界定定义了逐条遍历DOM结构的类型:NodeIterator,Tree沃克,那五个门类执行深度优先遍历(深搜)

          作者那时写了三个帮助函数:

NodeIterator类型

能够运用document.createNodeIterator方法成立实例,接收6个参数:root(源点),whatToShow(要访问的节点的数字代码),filter(NodeFilter对象,或意味着应当接受或拒绝某种特定节点的函数),entityReferenceExpansion(布尔值,是还是不是要壮大实体引用)

whatToShow是1个掩位码,以常量形式在NodeFilter类型中定义

NodeFilter.SHOW_ALL:展现全体

NodeFilter.SHOW_ELEMENT:呈现成分节点

NodeFilter.SHOW_ATT奥迪Q5IBUTE:性剧情点,由于DOM结构原因,实际上,这些值不可能接纳

NodeFilter.SHOW_TEXT:文本节点

NodeFilter.SHOW_CDATA_SECTION:显示CDATA节点,对HTML没用

NodeFilter.SHOW_ENTITY_REFERENCE:实体引用节点,对HTML没用

NodeFilter.SHOW_ENTITYE:实体节点,对HTML没用

NodeFilter.SHOW_PROCESSING_INSTRUCTION:处理指上除点,对HTML没用

NodeFilter.SHOW_COMMENT:注释节点

NodeFilter.SHOW_DOCUMENT:文档节点

NodeFilter.SHOW_DOCUMENT_TYPE:文书档案类型节点

NodeFilter.SHOW_DOCUMENT_FRA创新霉素ENT:文书档案片段节点,对HTML没用

NodeFilter.SHOW_NOTATION:符号节点,同上

除NodeFilter.SHOW_ALL外,可以应用按位或操作符组合三个选取

种种NodeFilter对象唯有3个方法:acceptNode(),再次来到NodeFilter.FILTE奥迪Q伍_ACCEPT或者NodeFilter.FILTER_SKIP,NodeFilter是3个架空类型,不可能直接开立实例,需要时方可创建叁个含有accpetNode方法的对象,传入createNodeIterator即可

例:

var filter = {
    acceptNode:function(node){
        return node.tagName.toLowerCase() == "p" ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
    }
};
var iterator = document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT,filter,false);
//或者使用一个与acceptNode方法类似的函数
var filter = function(node){
    return node.tagName.toLowerCase() == "p" ?
            NodeFilter.FILTER_ACCEPT :
            NodeFilter.FILTER_SKIP;
};

NodeIterator类型八个重大方法:nextNode(),previousNode()

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

TreeWalker

NodeIterator的更尖端版本除了NodeIterator的三个法子外,还提供用于在分歧倾向遍历DOM的法门:

parentNode():遍历到最近节点父节点

firstChild():到近来节点的首先身形节点

lastChild():到当下节点的最终贰个子节点

nextSibling():到当下节点的下三个同辈节点

previousSibling():到当前节点的上3个同辈节点

行使document.createTree沃克方法,与document.createNodeIterator类似接收肆各参数:根节点,要体现的节点类型,过滤器,是还是不是扩张实体引用布尔值

不同:filter返回值:除了 NodeFilter.FILTER_ACCEPT,NodeFilter.FILTER_SKIP,还有NodeFilter.FILTER_REJECT,NodeFilter.FILTER_SKIP会进入子节点搜索,而NodeFilter.FILTE帕杰罗_REJECT则跳过1切子节点树,剪枝算法

Tree沃克类型还有叁个特性:currentNode,通过改动此属性还是能更改搜索源点

           
作者那儿写了一个openClassScan参数,解释一下,这一个参数是为着缓解类似于<div
class = “a
b”></div>那种,因为壹旦要辅助通过API查询如class:a,那么必要各样节点都认清是不是contain这一个class,相比较费时间,而本身以为很多时候不须求,所以私下认可自身关闭了。

范围(有点难)

DOM二级在Document类型中定义了createRange方法。属于document对象,使用hasFeature或直接检查实验该办法,能够分明浏览器是或不是辅助范围

注:新创设的范围直接与创制它的文书档案关联,只可以用于当前文书档案

各个范围由多个Range实例表示,下列属性提供了当前范围在文书档案中的音讯:

startContainer:蕴涵限制源点的节点(选区中首先身长节点的父节点)

startOffset:范围在startContainer中起源的偏移量,若startContainer是文本节点,注释节点,CDATA节点,则startOffset就是限制起源从前跳过的字符数量,不然就是限制中率先身形节点的目录

endContainer:包蕴限制重点的节点(即选区中最后2个节点的父节点)

endOffset:范围在endContainer中终点的偏移量,与startOffset规则1样

commonAncestorContainer:startContainer和endContainer共同祖先节点在文书档案树地方最深的不行

           
PS:使用了原生的document.getElementsByClassName的必然不受那个影响的。

1、使用DOM范围达成简单选取

动用selecNode和selectNodeContents方法应用范围选取文书档案一部分,四个章程都接受二个参数:DOM节点,selectNode采纳一切节点,selectNodeContents采用节点的子节点

例:

<!DOCTYPE html>
<html>
    <body>
        <p id="p1"><b>Hello</b> world!</p>
    </body>
</html>

var range1 = document.createRange();
    range2 = document.createRange();
    p1 = document.getElementById("p1");
range1.selectNode(p1);
range2.selectNodeContainer(p1);

结果

www.301.net 11

调用selectNode时,startContainer,endContainer,commonAncestorContainer都是传播的父节点,也正是document.body,startOffset等于给定节点在其父节点的childNodes集合中的索引,endOffset=startOffset+一,因为只选了1个节点

调用selectNodeContainer时,startContainer,endContainer,commonAncestorContainer都以流传的节点,约等于<p>成分,startOffset始终等于0,因为范围从给定节点的首先个头节点早先,endOffset等于子节点数量,本例中是二

二、使用DOM范围达成复杂选取(关键)(难度在此处,消除了这么些,之后的操作就没啥大题材,必要再探讨商量)

三、操作DOM范围中的内容

4、插入DOM范围中的内容

5、折叠DOM范围

6、比较DOM范围

7、复制DOM范围

8、清理DOM范围

           笔者把每一个查询如:tp.dom.query(“#aa
input”)分为三种,一种为简便询问(也正是如查询:#aaa),其它1种是错综复杂查询,各种复杂查询都以由许多简短询问构成的,比如#aaa
input,就足以切成:#aaa和input。

IE八及更早版本中的范围

IE捌及更早版本并不援助DOM范围(IE便是这么拽),扶助类似概念文本范围

           所以,在每一种查询的最伊始,供给将传递的查询格式化,比如#aa
>input那种格式化为:#aa >
input,多个空格变为二个空格,>两边必须有1个空格等。

第三7章,错误处理与调节

应用try-catch,throw语句获得肯定的错误消息

格式:

try{
     //可能出错的代码
}catch(error){
     //出错时应该怎么处理的代码
}

finally语句是try-catch语句的可选语句,但finally语句一经使用,无论怎么样都会执行。有了finally语句,catch就成了可选的

注:IE七及更早版本有bug:除非有catch语句,不然不实施finally语句,(又来拽一波了)

         
 之后写一个助手函数,判定是或不是是复杂查询,借使是,那么切开查询字符串,切成数组。

漏洞万分多类型

Error

EvalError

RangeError

ReferenceError

SyntaxError     //语法错误

TypeError        //类型错误

URIError

Error是基类,其余品种都一连自该类,全体错误类型共享同壹组属性

伊娃lError在行使eval是抛出,不难说,就是从未把eval当函数用,就抛出荒唐

RangeError在数值高于相应范围时接触

var item = new Array(-20);     //触发
var item = new Array(Number.MAX_VALUE);     //触发

找不到目的,爆发ReferenceError

变量保存意外类型,访问不设有的办法,都会抛出TypeError

var o = new 10;
alert("name" in true);
Function.prototype.toString.call("name");
//以上都会抛出TypeError

encodeU奥迪Q7I,decodeU福睿斯I,会抛出ULacrosseIError,少见,那两货的容错性高

遇见throw操作符,代码马上甘休执行

throw 1234;
throw "hello";
throw true;
throw {name:"js"};
//以上代码都是有效的

还是能创制自定义错误音信:

throw new Error("some message");
throw new SyntaxError("syntax error");
throw new ReferenceError("reference error");

仍是能够够创设自定义错误类型:(通过继承Error)

function CustomError(message){
     this.name = "CustomError";
     this.message = message;
}
CustomError.prototype = new Error();
throw new CustomError("my message");

           我认为:#aa
input那种实际上正是经过document.getElementById查询之后然后查询它的子孙节点中的全体满足tagName为input的成分;而#aaa
>
input那种就是查询它的孩子节点中是或不是有那种满足条件的要素。以往全方位工艺流程比较简单了,对于叁个复杂查询,首先进行一个简约询问,然后遵照查询的结果集合,举行一次遍历,对各类节点查询它的男女节点或子孙节点,将装有满意条件的放入到此外贰个数组,假使该数组为空,那么直接回到空数组,不然,继续展开下三回查询(依然查询孩子节点或子孙节点)。

不当事件

其它未有经过try-catch处理的不当都会触发window对象的error事件

         
 作者觉着,就那样2个成效相比简单的query就够了,不必要实现类似于jquery里面包车型客车如此繁复的查询,假诺要使用它,其实也很简短,因为jquery的询问引擎sizzle已经开源,完全能够将它进入到那一个库,而以后toper也是这么做的,要调用sizzle就动用:

广阔错误类型

类型转换错误

数据类型错误

通讯错误

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

调剂技术

将新闻记录到控制台

将错误信息记录到当前页面

抛出错误

         
感觉JS的包容性真心很脑瓜疼啊,就比如在DOM那叁只,为了合作,作者都做了十分长日子。当然,DOM那壹道必然不止这么一点剧情,一时也不写了。

常见IE错误(IE,最难调节和测试js错误的浏览器,难怪那么拽)

操作终止

不算字符

未找到成员

不解运转时不当

语法错误

系统不能够找到钦赐财富

          除了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;
};

       
我看了1晃,差别的库的判断格局差异等,小编此时使用的是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,真心搞不懂,那是要逆天啊?

     
 除了那种判断格局,还是能通过判定是还是不是有某三个函数或某3个变量来判断,那种判断形式本人遗忘叫什么名字了,反正在此之前那种叫浏览器嗅探。

     
 除了代码之外,工具也很重点,另1篇日记介绍JS工具的:

       
对动画片有趣味的童鞋,可以看看自身的近期求学JS的觉悟-二,关于动画的。

     
 好呢,貌似又超时了,先就像此呢,感觉每便写这种日志都会花费见惯司空时刻。

Post Author: admin

发表评论

电子邮件地址不会被公开。 必填项已用*标注