组件化的Web王国,自定义标签在IE6

by admin on 2019年1月31日

自定义标签在IE6-8的泥沼

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

初稿出处:
司徒正美   

兴许未来前端组件化之路都是自定义标签,但那东西早在20年前,JSTL已在搞了。现在Web
Component还只有webkit扶助。但一个组件库,还索要一个相当的标识它们是一块的。但是那几个XML已经帮我们搞定了,使用scopeName,如”<xxx:dialog>”。在本人继续往下想什么处理怎样为那个标签绑定数据,与任何零件通讯,管理生命周期,等等大事以前,我还有一个不得不面对的难题,就是什么包容IE6-8!

例如以下一个页面:

必发88 1

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

必发88 2
必发88 3
必发88 4
必发88 5

咱俩会意识IE6下实际是多出许多标签,它是把闭标签也变成一个独立的要素节点

必发88 6

那些AA:DIV标签被开膛破肚,里面子节点全体暴出来,成为其兄弟节点了。由此想包容它,就要费点劲。有个多个情景必要考虑,1是用户已经将它写在页面上,情状同上;2是用户是将它坐落字符串模版中,那么些用正则搞定。可是正则假若撞倒复杂的属性名,照旧会晕掉。由此我或者打算选用原生的HTML
parser。换言之,字符串,我仍然会将它变成节点。这么办吧?!我想了成百上千方法,后来或者选择VML的命名空间法搞定!

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

必发88 7
必发88 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 收藏
评论

必发88 9

     
 还记得我大二的时候开始接触JS,那个时候从体育场馆借了N多的图书,然前边看边用editplus写,然后遭遇难点,种种DEBUG,在做项目的时候,各样包容性难点,真是痛苦啊。由于品种须求尽早写完,所以就从头接触了jquery,仍旧从体育场馆抱了几本书,然后下载了jquery源码,然前边看书籍边写代码,看了几章之后,觉得貌似简单,然后就从网上下载了jquery的文档,对照着文档,对其调用搞获得底比较清楚了。

第11章, DOM扩展

本文由 埃姆杰 翻译。未经许可,禁止转发! 英文出处:Future Insights。

       
现在总的来说,我觉得学习jquery反而使自己走了弯路,用jquery是相比便于,也决不考虑包容性难点了,而且调用相当简单优雅,可是,反而我对原生js感觉越是陌生了,也促成了前边感觉完全离不开jquery了,想去写一个XXX组件,想了一下,思路有了,然后写的时候蒙受种种难题,然后就又回到jquery了。

选择符 API

Selector API
Level1
主干措施querySelector 、querySelectorAll,包容的浏览器可以利用 Document,Element 实例调用它们,帮忙浏览器:IE8+,Firefox3.5+,Safari3.1+,chrome,Opera10+

内容提要

运用过多独立组件营造应用程序的想法并不出奇。Web
Component的出现,是重复回忆基于组件的应用程序开发形式的好机会。大家得以从那些历程中受益,精通怎么利用现有技术已毕目的,并且在将来做出自己的前端Web应用。

       
 从上年暑假的时候,我说了算离开jquery了,jquery是一把双刃剑,开发的时候是便宜,不过,作为一个初学者,我以为那是很不利的。

querySelector方法

收起一个 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”);

如何是组件?

软件开发是一个语义丰盛(术语平常持续一个意味)的领域。很显然,那里的“组件”是一个很泛的叫做,所以有须要指明我们想要表明的,在前者Web应用的言语环境中的意思。

前者Web应用中的组件,是指部分企划为通用性的,用来打造较大型应用程序的软件,那个零件有多样表现格局。它可以是有UI(用户界面)的,也足以是用作
“服务”的纯逻辑代码。

因为有视觉上的表现方式,UI组件更便于精晓。UI组件简单的例子包蕴按钮、输入框和文本域。不论是希腊雅典包状的菜系按钮(无论你是还是不是喜欢)、标签页、日历、选项菜单或者所见即所得的富文本编辑器则是一对进一步高档的例子。

提供服务类型的零部件可能会令人为难明白,那连串型的例证包涵跨浏览器的AJAX扶助,日志记录或者提供某种数据持久化的成效。

基于组件开发,最重视的就是组件可以用来整合任何零件,而富文本编辑器就是个很好的例子。它是由按钮、下拉菜单和有些可视化组件等构成。另一个事例是HTML5上的video元素。它一样富含按钮,也还要富含一个能从视频数据流渲染内容的元素。

       
 然后就起来下载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类型新增了一个办法matchesSelector,接收一个参数,CSS选择符,若调用元素与该选用符匹配重返true,否则重临false

注:到二零一一年年中还尚无浏览器帮助此情势,可是,IE9+通过msMatchesSelector,Firefox3.6+通过mozMatchesSelector,Safari5+和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")){
     //操作
}

模块

您或许听说过 “组件是自发模块”的传道。好呢,感谢它,我们又要表达那里的术语!

你可能会以为“组件”的布道更为适合用来描述UI,而“模块”更契合描述提供劳动的职能逻辑。而对此自身来说,模块和零部件意思相近,都提供团体、聚焦和打包,是与某个意义单位有关的。

       
开头写的感觉真是痛苦啊,什么都不懂,所以就去看了看tangram的源码,为何看tangram呢,其实原因比较搞笑,当时校招的时候我面试百度前端,被刷掉了,当时面试官让自己看看它们百度使用的JS库tangram,我就想看看它们格外库到底有什么了不起的。。。

要素遍历

对于元素间空格,IE9及前面并不会回到文本节点,其余浏览器都会,为此Element
Traversal规范新定义属性:

childElementCount:再次回到子元素个数,不包罗文件节点和注释

firstElementChild:firstChild元素版

lastElementChild:lastChild元素版

previousElementSibling:previousSibling元素版

nextElementSibling:nextSibling元素版

行使上述因素得以不要担心空白文本节点

辅助Element Traversal规范的浏览器IE9+,Firefox3.5+,Safari4+,Chrome和Opera10+

高内聚

又是一个软件工程的高频词! 咱俩将有关的一些作用团体在一齐,把任何封装起来,而在组件的例子中,就可能是有关的功能逻辑和静态资源:JavaScript、HTML、CSS以及图像等。那就是我们所说的内聚。

那种做法将让组件更便于保险,并且这么做之后,组件的可看重性也将增加。同时,它也能让组件的效能明确,增大组件重用的可能性。

       
写这么些库,首先利用了命名空间,我比较欣赏toper,所以我首先定义了一个变量:

HTML5

H5新增了好多API,致力于简化CSS类的用法

可重用

您看看的演示组件,越发是Web
Component,更关怀可接纳的题材。功效明显,完结清晰,API易于通晓。自然就能促进组件复用。通过创设可选拔组件,大家不但有限支撑了 DRY(不要再一次造轮子)标准,还得到了相应的好处。

此间要提拔: 不要过分尝试营造可接纳组件。你更应当关怀应用程序上所急需的那么些特定部分。固然将来相应需要现身,或者零部件的确到了可选拔的地步,就花一点附加时间让组件重用。事实上,开发者都爱好去创建可选拔功用块(库、组件、模块、插件等),做得太早将会让您后来痛心不堪。所以,吸取基于组件开发的其余利益,并且接受不是独具组件都能重用的事实。

var tp = tp || {};

1、getElementsByClassName方法

document及所有HTML元素都足以调用该办法

此方法接收一个参数,包蕴一个或多少个类名的字符串,再次来到带有指定类的装有因素结合的NodeList

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

在要素上调用,只会回来后代元素中的匹配,在document上调用,再次来到所有

注:因为再次回到的是NodeList,所以,会设有与有着重回NodeList的点子同样的性质难点

协助的浏览器IE9+,Safari3.1+,Firefox3+,Chrome,Opera9.5+

可互换

一个意义显然好组件的API能令人擅自地改成其内部的成效达成。假如程序内部的零部件是松耦合的,那实在能够用一个组件轻易地更迭另一个组件,只要遵循千篇一律的 API/接口/约定。

假定你采用GoInstant提供的实时效应劳务组件,那她们下周关门服务如此那般的新闻会影响到您。但是,只要提供了同一的数目同步API,你也得以自行创设利用一个 FirebaseComponent 组件或者 PubNubComponent 组件。

       
那种艺术也是以史为鉴了tangram的写法,采纳对象字面量的款型。那样所有toper定义的方法都位于了tp那个私有空间内了,比如对DOM的操作就置身tp.dom中。

2、classList属性

H5为具备因素添加了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方法,确定文档是或不是得到宗旨

落实那三个属性浏览器IE4+,Firefox3+,Safari4+,Chrome,Opera8+

当今就从头创设组件

在 Caplin
Systems 打造基于组件的自有应用程序时,我动用了几条标准和举行。这几个标准由 BladeRunnerJS(BRJS) 开源工具集支撑。它被称作”BladeRunnerJS”
是因为大家将顺序功能都封装在称作 Blades 的事物中。Blade是足以在某个应用中引用的法力特色,不过不可以在程序间重用。当功用真的
变得尤为通用的时候,我们将相应的定义移到库文件中,供各种程序间选拔。特定应用中的组件(blade)和我们先后间的通用组件可以选拔,大家只要找到最好满意急需的任何库和框架。

那就是说,现在哪些库和框架可以援救大家创设组件呢?

在支配营造利用时应选择何种技术时,只须求探视流行的 TodoMVC 网站就可以见到大批量可供选拔的前端库和框架。你或许会认为任何一种方案都能用来营造基于组件的应用程序。可是,他们之中的局地方案内置了对组件的襄助。其中相比较有名的是AngularJS、Ember
和 React。

     
我动用的构造是core+组件的主意,tp.core.js(压缩后为tp.core-min.js),而其余的零部件每个组件一个文书,而组件之间可能存在依靠关系,那种看重关系就经过英特尔解决。

H5扩展了HTMLDocument

组件间是什么通讯的?

在深入示例从前有必不可少简单地关系组件间通讯的标题。借使组件之间是“独立”、“模块化”的,他们又是如何相互通讯的吧?

最引人注目的答案就是让组件间相互引用并通过她们之间的API交互。那样做的难点就在于,那种做法会让组件相互珍惜。长时间内或许还好,一段时间未来,你在改动程序的时候程序会失控,修改一个组件就会对另一个零部件发生极大的震慑。决定移除一个不可能推动预期价值组件可能会让您的应用程序为止工作,因为它背后会有数个零部件依赖于它。

组件化的Web王国,自定义标签在IE6。那时,解决方案是提供松耦合的,让组件之间很少或者大约不清楚互相的方案。组件并不直接开立其他零件,在他们需要通讯的时候,他们经过“接口/约定”或者经过 “服务”。大家在创设BRJS程序时考虑了许多那个地点的事物,并且使用 ServiceRegistry 访问用于组件间通信的劳动或者是Web
API那般的资源。Angular和Ember接纳了劳动和依傍注入竭泽而渔那类难题。

     
在并未写这几个库以前,即便是自家利用jquery,每一个JS文件我都是直接在HTML文件中选取script标签写进去的,而近期亟需动用那种异步模块加载的措施,借使要动用非焦点模块,那么需求:

1、readyState属性

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

支撑的浏览器IE4+,Firefox3.6+,Safari,Chrome,Opera9+

以身作则组件my-avatar

为了显得大家什么样用这么些库和框架营造最基本的组件,大家建立了一个包罗UI,用于取回和体现用户头像的概括示例。在可能的情景下,该器件会有 my-avatar 标签,会从以下三个属性中收获头像:

  • service 允许设置一个劳务。例如 twitter 或者 facebook
  • username 用于取回该用户名相对应的头像
tp.use(["tp.a","tp.b"],function(a,b) {

})

2、包容模式

AngularJS

AngularJS 可能是现在用来营造程序最流行的前端解决方案了。作为创小编的谷歌(Google),重新思考HTML,考虑怎样重新发明,满意近日Web开发的需求。

Angular中可以动用自定义指令概念组件。之后,你可以利用 HTML
标记注明自定义组件。

查阅代码演示: 

以此事例显示了采纳Angular指令的粗略程度。值scope 定义了从
 my-avatar 元素中获取,并且之后用来打造相应的img标签和渲染成用户头像的性质。

     
使用use格局,它会活动去下载tp.a.js和tp.b.js,下载已毕未来,执行回调函数。

3、head属性

H5新增document.head属性,得到<head>元素,协助浏览器Chrome,Safari5+

Ember

框架与库的争论旷日持久,总的来说框架是威逼你按某种格局做事情,所以它是严酷的。很显明,Angular是个框架,而Ember的撰稿人,Yehuda
Katz和TomDale也很情愿把Ember看作框架。

Ember 有对它称作组件的内建协助。Ember
Components背后的见地是尽可能的向Web
Components看齐,当浏览器辅助允许时,就可以很便宜地迁移到Web
Components中。

翻看代码演示: 

地点的事例中应用了 handlebars 做模板,所以元素的概念不是相同种语法。

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

字符集属性

H5新增charset属性,表示文档实际利用字符集,可更改,支持浏览器IE,Safari,Chrome,Opera。Firefox协助Characterset

defaultCharset属性,表示依据默许浏览器和操作系统设置,确定用什么字符集,援救浏览器IE,Safari,Chrome

组件化的Web王国,自定义标签在IE6。可以自定义非标准属性,要添加前缀data-,dataset属性可以访问,dataset是DOMStringMap的实例

React

React 即便是个新人,不过却早已有过多的接济者。它由非死不可开发,并且已经完善用于Instagram的UI和一部分Facebook的UI。

动用React营造组件的引进方法是应用叫做 JSX 的事物来定义它们。那是一种“推荐在React上选拔的JavaScript语法转换”。请不要为此分心。他们早已在文档中提出,那些想法就是用来扶助你在JavaScript中写出HTML标记的。

自己不是说您并不得以直接在HTML中添加标签,而必须利用JSX创设自己的零件。不过,只要你定义了一个零部件,你就足以选用那么些组件创建其余零件。

翻开代码演示: 

所以,组件使用的注解语法必要相应的HTML元素和对 React.RenderComponent 的调用。

 

插入标记

未来:Web Component和其他

Web
Component才是鹏程!正如名字所代表的那样,他们承诺将带来可以将效能封装成组件的浏览器原生帮忙。

本人将简单体现Web
Component并且演示大家明日得以什么选取它。尤其深刻的始末请参见本文末尾的 “外部资源” 一节。

他们提供的效益包蕴:

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

    });
});

1、innerHTML属性

读形式,再次回到与调用元素的所有子节点对应的HTML标记,包罗属性,注释,文本节点

写模式,根据指定值创制DOM树,然后用这一个DOM树替换原先所有子节点

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

注:限制:在半数以上浏览器中通过此属性插入<script>元素并不会实施其中的本子,IE8及更早版本可以,条件还挺多

不协理此属性的因素:<col>,<colgroup>,<frameset>,<head>,<html>,<style>,<table>,<tbody>,<thead>,<tfoot>,<tr>,在IE8及更早浏览器<title>也没有

自定义元素

我们在地点关怀的是用Angular、Ember和React构建 my-avatar 的事例。可能的场合下,那样的章程将以页面上或者模板上加上的自定义元素表示。Web
Component包含透过自定义元素赢得的原生辅助– 绝对是Web Component标准的着力组成部分。

概念新元素,包涵走访元素生命周期的一些事件例如曾几何时创设(createdCallback)、哪一天添加在DOM树上(attachedCallback)、什么日期从DOM树上分离(detachedCallback),曾几何时元素属性改变(attributeChangedCallback(attrName, oldVal, newVal))。

自定义元素的一个主要的有些就是有力量从原本元素增添,由此得到原有元素相应的成效。示例中我们扩大了 <img>元素 。

最终,大家所写的代码中,自定义元素正在并且倾向去做的就是将复杂的东西抽象化,让用户关怀于单个组件暴发的价值,从而用来营造尤其助长的效益。

   
 define的率先个参数是该器件的名字(须求唯一,所以我要么听从命名空间的方法写的),第三个参数是这一个组件所信赖的零件,第多少个参数是回调函数,也就是当信赖的组件下载达成之后,回调执行,而tp.modules.add就足以将以此模块加载到全方位库中,那样的话才能选择tp.use调用。

2、outerHTML属性

读形式,再次来到与调用元素的所有子节点对应的HTML标记

写情势,根据指定值成立DOM树,然后用那些DOM树替换原先元素

支撑的浏览器IE4+,Safari4+,Chrome,Opera8+。Firefox7及此前版本都不协助

Shadow DOM

还记得iframe们吧?大家还在使用它们,是因为他们能保险组件和控件的JavaScript和CSS不会潜移默化页面。 Shadow
DOM 也能提供那样的掩护,并且没有iframe带来的承受。正式的布道是:

Shadow
DOM的筹划是在shadow根下隐藏DOM子树从而提供包装机制。它提供了成立和维系DOM树之间的功能界限,以及给那几个树提供相互的职能,从而在DOM树上提供了更好的功效封装。

     
这种艺术本身在tangram中从不看到,我是看了天猫商城的KISSY之后攻读到的,也就是所谓的速龙(异步模块定义)。

3、insertAdjacentHTML方法

收起五个参数:要插入的职责,要插入的HTML文本,第三个参数必须是下列值之一

“beforebegin”,在当下元素之前插入紧邻的同辈元素

“afterbegin”,在此时此刻因素插入一个新的子元素或在首先个子元素往日插入新的子元素

“beforeend”,在当前因素以下插入一个新的子元素或在终极一个子元素之后插入新的子元素

“afterend”,在此时此刻因素之后插入一个同辈元素

HTML导入

俺们长日子往日就足以导入JavaScript和CSS了。 HTML导入功能提供了从其余HTML文档中导入和选定HTML文档的力量。那种简单性同时意味着能够很方便地用部分零件营造另一对组件。

最后,那样的格式很卓越,适合可接纳组件,并且可以用你最欢乐的包管了然决方案发布(例如: bower、 npm 或者 Component)。

     
暂时速龙的贯彻格局是由此setInterval,然则即将被重构必发88 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,Firefox9+,Chrome,Opera。

DOM Level 3
compareDocumentPosition方法也足以确定节点间涉及,帮忙浏览器IE9+,Safari,Firefox,Chrome,Opera9.5+。再次来到用于表示多少个节点间的涉及的位掩码

掩码

节点关系

1

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

2

居前

4

居后

8

包含

16

被包含

模板

咱俩中的许四个人曾经应用像handlebars、mustache或者underscore.js中的模板那样的化解方案(似乎我们在上头的Ember示例中用的同一)。Web
Component通过 template元素 提供了模版的原生支持。

原生模板让你可以表明分类为“隐藏DOM”不过解析成HTML的号子片段。他们在页面加载时从没用处,然而可以在运转时实例化。他们可以被搜寻到 ,然而在插入活动的DOM树前不会加载任何相关资源。

     
我在此以前写了一篇日记来促成英特尔,当然,作用低下,反正大家看看就行了

陈设文本

从没纳入H5规范的质量

Platform.js

不过,如同每一回提到新特性一样,我们无法确定浏览器是还是不是援救那些特征。

必发88 11

以至二〇一四年十二月27日,Web Component 的浏览器协理情形

一如既往,大家也能通过有些神奇的同盟代码,初始选用一些Web
Component所提供的功效。

必发88 12

有了包容库的Web Component辅助情状

好音信是多个开首进的浏览器厂商谷歌(Google)和Mozilla正在着力周详包容库
,援助大家使用Web Component。

以下示例浮现使用platform.js后大家可以怎么定义作为img元素伸张的my-avatar元素。最棒的是它能用到原生img元素的兼具机能。

查看代码演示: 

点击 HTML5 Rocks Custom Elements
tutorial 以查看创设自定义元素的更加多音讯。

注:如若你对platform.js感兴趣,也得以看看 bosonic。

原生技术的支撑目标就是给大家提供相应的创设基础。所以Web
Component并不是库和框架的末日信号。

     
然后就是事件了,事件是一个相比较恼火的工作,东西相比较多,我把它座落了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语法字符(>,<,”,&)进行编码

援救的浏览器IE4+,Safari3+,Chrome,Opera8+。Firefox不协理,但支撑类似属性textContent属性,textContent是DOM
Level 3规定的一个属性,IE9+,Safari3+,Chrome,Opera10+也支撑textContent

Polymer

Polymer 是演示营造基于原生Web
Component功效的一级示例。它提供了接纳的体制用来制造自定义的Polymer元素,并且提供了众多主干的UI组件,让你可以创设自己的应用程序。

必发88 13

上面你可以见见 my-avatar 元素的概括制造进程,同时大家也得到了想要的标志。

翻看代码演示: 

谷歌(Google)正在力图推进Polymer。请查看 Polymer getting started
guide 查看更加多示例。

     
首先是添加和移除事件监听器,由于IE和非IE选拔的主意不等同,IE选取attach伊芙nt和detech伊芙nt,非IE拔取add伊芙ntListener和removeEventListener,而且IE只协助冒泡(从脚下因素冒泡到根元素),而非IE帮衬冒泡和破获(从根元素捕获到当下元素)。最开头自己是那样做的:

2、outerText

除却作用范围伸张到了包括调用它的节点之外,outerText与innerText基本均等

X-Tag和Brick

Mozilla开发了协调的自定义元素
包容库,叫做 X-Tag。X-Tag是一个为启用Web
Component举办多项包容的库,并即将提供对Web Component的完全帮助。

以下就是选拔X-Tag的 my-avatar 自定义组件,与专业文档卓殊看似:

翻开代码演示:

Mozilla同时还创设了一个叫 必发88,Brick 的库,其中囊括X-Tag,提供“一组用来便于飞快打造Web应用程序的UI组件”,使用与谷歌(Google)的Polymer相似的方法。

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文档底层结构。DOM2和DOM3则在此基础引入越来越多互动能力,支持更尖端的XML特性。

总结

应用基于组件的架构创设应用程序有过多便宜,你能从现有的框架中学到,也能在创设前端Web应用程序时从引进的Web
Component中学习到。

这场组件化Web帝国的旅程,让大家在面临框架和工具的精选时三翻四复不决。不过,Web
Component会是终极的点灯!

Web
Component会提供创设应用程序的原生统一的艺术
。现有的框架很有可能会转而使用Web
Component或者注解怎么样与它一起使用。Ember的国策是让迁移到Web
Component尤其便宜,而Facebook的React则是出现说法整合的好例子,已经有一个 ReactiveElements 演示它了。因为Angular和Polymer都是谷歌的档次,他们很有可能会走到共同。

   
 也就是在一个函数内部去判断是或不是是IE,然后相应的履行相应的函数,可是那样,如若加上的风浪监听器很多,每一趟都if什么的,我个人感觉很糟糕,所以我背后添加了一个帮扶函数:

DOM2级:

主干:在1级基础上,为节点添加更加多措施和总体性

视图:为文档定义了依据样式音信的不比视图

事件:表达了怎么使用事件与DOM文档交互

体制:定义了怎样以编程格局来走访和更改CSS样式信息

遍历和限量:引入了遍历DOM文档和接纳其特定部分的新接口

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

表面资源(英文)

  • Eric Bidelman – Google I/O 2014 – Polymer and Web Components change
    everything you know about Web
    development
  • Ryan Seddon – Web Directions – Web Components, The Future of Web
    Development
  • Addy Osmani – LXJS – Componentize The Web: Back To The
    Browser!
  • WebComponents.org a place to discuss and evolve web component
    best-practices
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");

         
 那样,整个判定只须求执行一回,后边调用的时候只必要动用_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>

掺杂使用二种语言,命名空间用途才可以反映

DOM2级焦点为多数DOM1级方法提供一定于命名空间的版本解决难题

           那这样,tp.event.on就变得非常简单了:

1、Node类型变化

在DOM2级,包蕴下列特定于命名空间的特性

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

namespaceURI:命名空间URI或(未指定情形下)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);
         };

DOM3级在此基础再引入:

isDefaultNamespace(namespaceURI),指定的namespaceURI是不是是当前节点的默许命名空间

lookupNamespaceURI(prefix),重临给定的prefix的命名空间

lookupPrefix(namespaceURI),重返给定的namespaceURI的前缀

         
而且那样还有一个好处,此前的办法只可以利用冒泡格局,但后天,可以利用捕获,当然,只好非IE才能利用,那样在背后使用事件代理一些非冒泡的轩然大波的时候卓殊有用,比如blur和focus事件。

2、Document类型变化

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

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

createAttributeNS(namespaceURI,attributeName):使用给定的attributeName创立一个属于命名空间namespaceURI的新特性

getElementsByTagNameNS(namespaceURI,tagName):重回属于命名空间namespaceURI的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等,那里就隐瞒了。

3、Element类型变化

紧要涉及操作特性,新增方法如下

getAttributeNS(namespaceURI,localName):取得属于命名空间namespaceURI且名为localName的风味

getAttributeNodeNS(namespaceURI,localName):取节点

getElementsByTagNameNS(namespaceURI,tagName):再次回到属于命名空间的tagName元素的NodeList

hasAttributeNS(namespaceURI,localName):确定当前元素是还是不是有一个名为localName的表征,而且该特性的命名空间是namespaceURI。注意:DOM2主干,也大增一个hasAttribute方法,用于不考虑命名空间的情形

removeAttributeNS(namespaceURI,localName):删除特性

setAttributeNS(namespaceURI,qualifiedName,value):设置属于命名空间且名为qualifiedName的特征值为value

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

注:除第二个参数外,这几个艺术与DOM1级相关办法效果一样

         
在拔取事件代理的时候,我们平常要获得到事件的对象元素,而IE和非IE又是不一样等的,所以须要单独写一个函数:

4、NamedNodeMap类型变化

增产方法多数情状只针对特征应用

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

其余变化

         
常用的机能本来依旧阻止事件冒泡以及阻碍默许事件的暴发,很遗憾,IE和非IE处理方式仍旧不雷同的,比如阻止冒泡IE采纳的是cancelBubble,而此外浏览器选用的是stopPropagation,所以如故需求写:

1、DocumentType类型

增产属性:publicId,systemId,internalSubset,前八个象征文档类型注脚中的新闻段,在DOM1中不可能访问

使用: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(),用途:从一个文档中拿走一个节点,将其导入到另一个文档

注:每个节点都有一个ownerDocument属性,使用appendChild时传出的节点属于不相同文档,则会出错,importNode则不会

与Element的cloneNode方法万分相像,接收五个参数,要复制的节点,是还是不是复制子节点的布尔值

DOM2级视图添加defaultView属性,指向拥有给定文档的窗口,除IE外,都辅助,IE接济等价属性:parentWindow

DOM2级要旨为document.implementation对象规定三个新措施:createDocumentType(创设新的DocumentType节点,接收多少个参数:文档类型名称,publicId,systemId),creteDocument(接收三个参数:针对文档元素的namespaceURI,文档元素标签名,新文档的文档类型)

DOM2级HTML为document.implementation新增方法createHTMLDocument,接收一个参数:新创设的文档的标题,只有Opera和Safari扶助

       
 事件这一头实际上自己做了N多东西,可是出于讲不完,所以暂时不说了。

3、Node类型

唯一一个与命名空间无关变化,isSupported方法用于确定当前节点有所啥能力,接收七个参数:特性名,版本号,存在于hasFeature相同的标题

提出:最好如故采纳能力检测确定某个特性是或不是可用

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

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

isEqualNode是还是不是一致种类,具有格外属性(相同地点,相同值)

例:

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

DOM3级:setUserData,接收3个参数:要安装的键,实际多少,处理函数

getUserData传入相同的键可以拿走数量

处理函数接收5个参数:操作类型(1复制,2导入,3删减,4重命名),数据键,数据值,源节点,目的节点

        注意一下呀,由于JS变量效用域没有block,所以请不要使用下边那种:

4、框架变化

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保留字,不可能经过轻重写转换,DOM2级样式规定,对应对象属性名应是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或一个空荡荡)

var arr = new Array(),
    i;

操作样式表

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

使用于文档的有所样式表通过document.styleSheets集合来代表,通过length可以驾驭样式表数量,通过方括号法和item方法能够访问每一个样式表

          事件之后,当然就是DOM了,感觉每个库在那个地点都做了成百上千干活。

1、CSS规则

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

       
 首先是ready的判定,关于那些能够看我别的一篇日记:

2、创造规则

拔取insertRule方法,接收多个参数:规则文本,在何地插入规则的目录

接济浏览器:Firefox,Safari,Opera,Chrome。IE8及更早版本支持类似方法addRule,接收七个必选参数:采取符文本和CSS样式音信,一个可选参数:插入规则地点

提议:拔取从前介绍过的动态加载样式表的技巧

       
 那里我第一讲一下tp.dom.query,也就是查询咋办的,首先看望常用的询问有:#aa,.aa,input。

3、删除规则:慎用

deleteRule接收一个参数:要删减的规则的职位

       
 #aa那种比较简单,因为JS提供了API,也就是document.getElementById;input那种也正如好搞,因为JS有document.getElementsByTagName;可是.aa这种艺术就相比较纠结了,因为JS没有提供API,幸好,在有的浏览器中要么提供了API:document.getElementsByClassName,而那个尚未提供这一个API的就相比较喜剧了,只可以遍历所有节点,也就是应用document.getElementsByTagName(*):

遍历

DOM2级遍历和范围定义了逐条遍历DOM结构的品种:NodeIterator,Tree沃克,那七个种类执行深度优先遍历(深搜)

          我那儿写了一个赞助函数:

NodeIterator类型

可以拔取document.createNodeIterator方法创立实例,接收4个参数:root(起源),whatToShow(要拜访的节点的数字代码),filter(NodeFilter对象,或意味着应该接受或拒绝某种特定节点的函数),entityReferenceExpansion(布尔值,是不是要壮大实体引用)

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

NodeFilter.SHOW_ALL:显示所有

NodeFilter.SHOW_ELEMENT:显示元素节点

NodeFilter.SHOW_ATTRIBUTE:特性节点,由于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_FRAGMENT:文档片段节点,对HTML没用

NodeFilter.SHOW_NOTATION:符号节点,同上

除NodeFilter.SHOW_ALL外,可以使用按位或操作符组合多少个挑选

每个NodeFilter对象唯有一个方法:acceptNode(),重返NodeFilter.FILTER_ACCEPT或者NodeFilter.FILTER_SKIP,NodeFilter是一个抽象类型,不可以直接成立实例,必要时得以创立一个含有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():到眼前节点的上一个同辈节点

采纳document.createTree沃克方法,与document.createNodeIterator类似接收4各参数:根节点,要显得的节点类型,过滤器,是不是增添实体引用布尔值

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

TreeWalker类型还有一个性质:currentNode,通过改动此属性仍可以更改搜索起源

           
我此刻写了一个openClassScan参数,解释一下,这些参数是为了缓解类似于<div
class = “a
b”></div>那种,因为若是要扶助通过API查询如class:a,那么需求各种节点都认清是或不是contain这几个class,比较费时间,而我认为很多时候不须要,所以默许自己关闭了。

范围(有点难)

DOM2级在Document类型中定义了createRange方法。属于document对象,使用hasFeature或直接检测该措施,可以规定浏览器是或不是扶助范围

注:新创造的界定直接与成立它的文档关联,只可以用于当前文档

种种范围由一个Range实例表示,下列属性提供了当前范围在文档中的新闻:

startContainer:包蕴限制起源的节点(选区中第一身材节点的父节点)

startOffset:范围在startContainer中源点的偏移量,若startContainer是文本节点,注释节点,CDATA节点,则startOffset就是限制起源此前跳过的字符数量,否则就是限制中首先个头节点的目录

endContainer:包涵限制重点的节点(即选区中最终一个节点的父节点)

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

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

结果

必发88 14

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

调用selectNodeContainer时,startContainer,endContainer,commonAncestorContainer都是流传的节点,也就是<p>元素,startOffset始终等于0,因为范围从给定节点的首先身材节点开端,endOffset等于子节点数量,本例中是2

2、使用DOM范围完毕复杂选择(关键)(难度在此间,搞定了那些,之后的操作就没啥大标题,必要再商量商量)

3、操作DOM范围中的内容

4、插入DOM范围中的内容

5、折叠DOM范围

6、比较DOM范围

7、复制DOM范围

8、清理DOM范围

           我把每一个询问如:tp.dom.query(“#aa
input”)分为二种,一种为简便询问(也就是如查询:#aaa),其余一种是扑朔迷离查询,每个复杂查询都是由许多简练询问构成的,比如#aaa
input,就可以切成:#aaa和input。

IE8及更早版本中的范围

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

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

第17章,错误处理与调节

拔取try-catch,throw语句得到肯定的错误音讯

格式:

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

finally语句是try-catch语句的可选语句,但finally语句一经使用,无论如何都会实施。有了finally语句,catch就成了可选的

注:IE7及更早版本有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

encodeURI,decodeURI,会抛出URIError,少见,那两货的容错性高

蒙受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事件

         
 我以为,就这么一个职能相比较简单的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;
};

       
我看了一晃,区其余库的论断方式差别,我此时使用的是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,关于动画的。

     
 好呢,貌似又超时了,先就这么吧,感觉每一次写那种日志都会损耗见惯司空时光。

发表评论

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

网站地图xml地图