javascript高级程序设计学习笔记(五)---DOM(2)

DOM2、DOM3

DOM变化

扩展了API,以满足操作XML的所有需求,提供更好的错误处理。实现了对明明空间的支持。

  • XML命名空间

    XHTML支持XML命名空间。
    命名空间使用xmlns特性指定,包含着< html >元素中。

样式

  • 访问样式

    HTML元素在javascript中有个style属性,是CSSStyleDeclaration的实例,包含通过HTML的style特性指定的所有样式,不包含外部样式表或嵌入样式表的样式。

var myDiv = document.getElementById('mydiv')
  myDiv.style.backgroundColor = 'red'
  myDiv.style.cssFloat = left
  

为style提供方法和属性

  cssText,访问style特性中的css代码
  length,获取元素的CSS属性数量
  getPropertyValue(propertyName),返回给定属性的字符串值

计算的样式

	  getComputdeStyle()
	  接受两个参数:要取得计算样式的元素和一个伪元素字符串,
	  返回一个CSSStyleDeclaration对象,包含当前元素的所有计算的样式
  • 操作样式表

    使用CSSStyleSheet类型表示样式表,包括通过< link >元素包含的样式表和在< style >中定义的样式表,但是该类型只读。该表继承于StyleSheet。

    document.styleSheets
    document.styleSheets.length
    document.sheet //(IE不支持)
    
    CSSRule对象,表示样式表中每一条规则
    cssText,返回整天规则对应的文本。(IE不支持)
    parentRule,如果当前规则是导入规则,这个属性引用的就是导入规则
    style
    type
    

    创建规则

    insertRule()
    sheet.insertRule("body {background-color:silver}",0);	
    addRule()(IE8及更早版本)
    

    删除规则

    deleteRule()
    removeRule()
    
  • 元素大小

    • 偏移量
  • offsetHeight

    • 元素在垂直方向上占用的空间
  • offsetWidth

    • 元素在水平方向上占用的空间
  • offsetLeft

    • 元素的左外边框至包含元素的左内边框之间的像素距离
  • offsetTop

    • 元素的上外边框至包含元素的上内边框之间的像素距离

    要知道某个元素在页面上的偏移量,需要将这个元素的offsetLeft和offsetTop与其offsetParent的相同属性相加,循环到根元素。

 function getElementLeft(ele){
    
    
	      var actualLeft = ele.offsetLeft;
	      var current = ele.offsetParent;
	  
	      while (current !=null){
    
    
	          actualLeft += current.offsetLeft;
	          current = current.offsetParent
	      }
	      return actualLeft;
	  }
	  
	  function getElementTop(ele){
    
    
	      var actualTop = ele.offsetTop;
	      var current = ele.offsetParent;
	  
	      while (current !=null){
    
    
	          actualTop += current.offsetTop;
	          current = current.offsetParent
	      }
	      return actualTop;
	  }
- 客户区大小

  等于元素内容及其内边距所占空间大小,不计滚动条
  clientHeight
  clientWidth
  function getView(){
    
    
	      if(document.compatMode == "BackCompat"){
    
    
	          return{
    
    
	              width:document.body.clientWidth,
	              height:document.body.clientHeight
	          }
	      }else{
    
    
	          return{
    
    
	              width:document.documentElement.clientWidth,
	              height:document.documentElement.clientHeight
	          }
	      }
	  }
  • 滚动大小

    等于包含滚动内容的元素的大小
    scrollHeight,没有滚动条情况下,等于元素内容总高度
    scrollWidht,没有滚动条情况下,等于元素内容总宽度
    scrollLeft,被隐藏在内容区域左侧的像素数
    scrollTop,被隐藏在内容区域上方的像素数
    
    在有滚动条时:
    
    在没有滚动条时
    IE(标准模式),scrollWidth和ScrollHeight等于文档内容区域,
    client Width和clientHeight等于视口大小
    Opera、Safari、Chrome中,scrollWidth和ScrollHeight等于视口大小,
    client Width和clientHeight等于文档内容区域
    
    • 确定元素大小

      一般来说,right和left差值与offsetWidht相等,bottom和top差值与offsetHeight相等。

 function getBoundingClientRect(ele){
    
    
	      var scrollTop = document.documentElement.scrollTop;
	      var scrollLeft = document.documentElement.scrollLeft;
	  
	      if(ele.getBoundingClientRect){
    
    
	          if(typeof arguments.callee.offset != 'number'){
    
    
	              var temp = document.createElement("div");
	              temp.style.cssText = "position:absolute;left:0;top:0";
	              document.body.appendChild(temp);
	              arguments.callee.offset = -temp.getBoundingClientRect().top-scrollTop;
	              document.body.removeChild(temp);
	              temp = null;
	          }
	          var rect = ele.getBoundingClientRect();
	          var offset = arguments.callee.offset;
	          return {
    
    
	              left:rec.left+offset,
	              right:rec.right+offset,
	              top:rec.top+offset,
	              bottom:rec.bottom+offset,
	          }
	      }else{
    
    
	          var actLeft = getElementLeft(ele);
	          var actTop = getElementTop(ele);
	          return {
    
    
	              left:actLeft-scrollLeft,
	              right:actLeft+ele.offsetWidth - scrollLeft,
	              top:actTop-scrollTop,
	              bottom:actTop+ele.offsetHeight-scrollTop
	          }
	      }
	  }

遍历

两个类型用来完成顺序遍历(深度优先)DOM结构:NodeIterator和TreeWalker。

  • NodeIterator

使用createNodeIterator()方法接受四个参数:

 - root:想要作为搜索起点的树中的节点  
 -  whatToShow:表示要访问哪些节点的数字代码  
 - filter:一个NodeFilter对象  
 -  entityTeferenceExpansion:布尔值,表示是否要扩展实体引用。
  var filter = {
    
    
      accepNode:function(node){
    
    
          return node.tagName.toLowerCase() == "p"?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP;
      }
  };
  
  var iterator = document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT,filter,false);
  
  
  NodeIteratot类型两个主要方法时nextNode和previousNode。
  var iterator = document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT,filter,false);
  var node = iterator.nextNode();
  while(node!==null){
    
    
      console.log(node.tagName);
      node = iterator.nextNode();
  }
  • TreeWalker

用于遍历的方法:

 -next Node()
 - previousNode() 
 - parentNode()  
 - firstChild()  
 - lastChild() 
 - nextSibling()  
 - previousSibling()

使用createTreeWalker()创建对象

范围

  • 用DOM范围实现选择

DOM2中使用createRange()方法创建范围。并且新建的范围直接与创建它的文档关联在一起,不能用于其他文档,然后可以使用范围选择特定部分。
Range类型提供的属性:

 - startContainer:范围起点的节点 
 -  startOffset:范围在起点的偏移量  
 - endContainer:包含范围终点的节点  
 - endOfffset:范围在
 - endContainer中的偏移量  

使用selectNode()选择当前元素及其子元素 使用selectNodeContents()选择当前元素中的子元素和文本节点

 var range = document.createRange();   range.selectNode(p1);  
   range.selectNodeContents(p2)
  • 用DOM范围实现复杂选择

       setStart()和setEnd(),接受两个参数:一个参照节点和一个偏移量值
       setStart的参照节点是startContainer,偏移量是startOffset
       setEnd的参照节点是endContainer,偏移量是endOffset
    
 var range1 = document.createRange();
      range2 = document.createRange();
      p1 = document.getElementById('p1');
      p1Index = -1;
      i,len;
  for (i=0,len=p1.parentNode.childNodes.length;i<len;i++){
    
    
      if(p1.parentNode.childNodes[i]==p1){
    
    
          p1Index = i;
          break;
      }
  }
  // 选择这个节点
  range1.setStart(p1.parentNode,p1Index);
  range1.setEnd(p1.parentNode,p1Index+1);
  // 该节点的内容
  range2.setStart(p1,0);
  range2.setEnd(p1.p1.childNodes.length)
  • 操作DOM范围的内容

       在创建范围时,内部会为这个范围创建一个文档片段,范围所属的全部节点都被添加到这个文档片段中。
       并且不补全缺少的开或闭标签,重新构建有效的DOM结构。然后可以对内容进行操作。
    
    • deleteContents(),从文档中删除范围包含的内容
    • cloneContents(),创建范围对象的一个副本,然后在文档其他地方插入该副本。
  • 插入DOM范围中的内容

    • insertNode():向范围选区的开始处插入一个节点

    • surroundContents(),环绕范围插入内容,接受参数:环绕范围内容的节点。

        提取范围i中的内容
        将给定节点插入到文档中原来范围所在的位置上
        将文档片段的内容添加到给定节点中
      
  • 折叠DOM范围

       折叠范围:范围中未选择文档的任何部分。
       在折叠范围时,其位置会落在文档中的两个部分之间,可能是范围选区的开始位置,或结束位置。
    

collapse()

  • 复制和清理范围

cloneRange()复制
detach(),从创建范围的文档中分离出该范围,然后解除引用。

事件

事件流

事件流描述从页面中接收事件的顺序。分为事件冒泡和事件捕获

  • 事件冒泡

    事件开始时由最具体的元素接收,然后主机向上传播到较为不具体的节点。沿着DOM树向上传播

  • 事件捕获

    事件是从不太具体的节点更早接收到事件,最具体的节点最后接收到事件。事件到达预定目标之前就可捕获。

  • DOM事件流

    三个阶段:事件捕获,处于目标阶段和冒泡节点。

事件处理

  • HTML事件处理

    例子:

 < input type="button" value="Click" οnclick="showMessage()" />

可以通过事件对象event,访问事件的属性等信息
该事件处理的缺点:
HTML与Javascript耦合太大

  • DOM0事件处理

    var btn = document.getElementById(“myBtn”);
    btn.onclick = function(){
    console.log(this);
    };在这里插入代码片
    这时候的事件处理程序在元素的作用域中运行,this引用当前元素

  • DOM2事件处理

    • addEventListener()
    • removeEventListener()
    • 都接受3个参数:要处理的事件名,作为事件处理程序的函数,布尔值(true为在捕获处理,false表示在冒泡阶段处理)
  var btn = document.getElementById("myBtn");
  btn.addEventListener("click",function(){
    
    
      console.log(this.id)
  },false)
  • IE事件处理
    • attachEvent()
    • detachEvent()
    • 接受参数:事件处理程序名称和事件处理程序函数
      事件处理程序在全局作用域运行,this等于window
  var btn = document.getElementById("myBtn");
  btn.attachEvent('onclick',function(){
    
    
      alert('Clicked');
  });

事件对象

事件对象包含了导致事件的元素、事件的类型以及其他特定事件相关的信息。

  • DOM中的事件对象

     event的属性:
       	 - bubbles,表示事件是否冒泡 
     	 -  cancelable,表示是否可以取消事件的默认行为  
     	 - currentTarget,事件处理程序当前正在处理事件的那个元素     
     	 - defaultPrevented,是否调用preventDefault()   detail,细节信息        
     	 - eventPhase,事件处理程序的阶段   preventDefault(),取消默认行为
     	 - stopImmediatePropagation(),取消进一步捕获或冒泡,同时阻止任何事件处理程序被调用   target,事件的目标 
     	 - type,被触发的事件类型
    
  • IE中的事件对象

通过window.event获取事件对象
属性:
cancelBubble,取消事件冒泡
returnValue,取消事件的默认行为
serElement,事件的目标
type,被触发的事件类型

事件类型

  • UI事件

UI事件值那些不一定与用户操作有关的事件。不一定与DOM规范有关

	  load,当页面完全加载后在window上面触发
	  unload,当页面完全卸载后在window上触发
	  error,当发送js错误时在window上触发
	  resize,当窗口或框架大小变化时,在window或框架上触发
	  scroll,当用户滚动滚动条的元素的内容时,在该元素上面触发。
  • 焦点事件

       blur,在元素失去焦点时触发
       DOMFocusIN,元素获得焦点时触发,等价focus,并且冒泡
       DOMFocusOut,元素失去焦点时触发,等价blur。
       focus,获取焦点时触发,不会冒泡
       focusin,元素获得焦点时触发,等价focus,但是冒泡
       focusout,元素失去焦点时触发
    

当焦点从页面一个元素移到另一个元素上,依次触发:

 -   focusout  
 -   foucusin 
 -   blur
 -   DOMFocusOut 
 -   focus  
 -   DOMFocusIn
  • 鼠标与滚轮事件

       click,单击鼠标按钮或回车键触发
       dbclick,双击鼠标
       mousedown,按下鼠标时触发
       mouseenter鼠标光标从原始外部首次移动到元素内时触发
       mouseleave,元素上方的鼠标光标移动到元素范围之外时触发
       mousemove,鼠标指针在元素内部移动时重复地触发
       mouseout,鼠标指针位于元素上方,然后用户将其移入另一个元素时触发
       mouseover,鼠标指针在一个元素外部,然后用户将其首次移入另一个元素边界内时触发
       mouseup,用户释放鼠标按钮时触发。
    

除了mouseenter和mouseleave,其他都会冒泡。
双击触发顺序:

	  mousedown
	  mouseup
	  click
	  mousedown
	  mouseup
	  click
	  dbclick

mousewheel,鼠标滚轮事件

 var elem = document.getElemenyById('div0');
  var clientX, clientY, isMoving;
  var mouseDownHandler = function(event) {
    
    
    event = event || window.event;
    clientX = event.clientX;
    clientY = event.clientY;
    isMoving = true;
  }
  
  var mouseMoveHandler = function(event) {
    
    
    if (!isMoving) return;
    event = event || window.event;
    var newClientX = event.clientX,
        newClientY = event.clientY;
    var left = parseInt(elem.style.left) || 0,
        top = parseInt(elem.style.top) || 0;
    elem.style.left = left + (newClientX - clientX) + 'px';
    elem.style.top = top + (newClientY - clientY) + 'px';
    clientX = newClientX;
    clientY = newClientY;
  }
  
  var mouseUpHandler = function() {
    
    
    isMoving = false;
  }
  
  addEvent(elem, 'mousedown', mouseDownHandler);
  addEvent(elem, 'mouseup', mouseUpHandler);
  addEvent(elem, 'mousemove', mouseMoveHandler);
  • 客户区坐标位置

    鼠标事件的视口位置信息保存在clientX和clientY中
    
  • 页面位置坐标

    页面坐标保存在pageX和pageY中。
    坐标从页面本身而非视口的左边和顶边计算。页面没有滚动时,与clientX、clientY的值相等
    
  var div = document.getElementById("myDiv");
	  EventUtil.addhandler(div,"click",function(event){
    
    
	      event = EventUtil.getEvent(event);
	      var pageX = event.pageX;
	          pageY = event.pageY;
	          if(pageX === undefined){
    
    
	              pageX = event.clientX + (document.body.scrollLeft ||document.documentElement.scrollLeft)
	          }
	          if(pageY === undefined){
    
    
	              pageY = event.clientY + (document.body.scrollTop ||document.documentElement.scrollTop)
	          }
	          console.log(pageX,pageY);
	  })
  • 屏幕坐标位置

    screenX和screentY属性确定鼠标事件发生时指针相对于整个屏幕的坐标信息
    
  • 相关元素

    mouseover事件,主要目标时获得光标的元素,相关元素就是失去光标的元素
    mouseout事件,主要目标时失去光标的元素,相关元素时获得光标的元素
    
  • 键盘与文本事件

       keydown
       keypress
       keyup
       按下一个字符键时,触发顺序:
       keydown(文本框变化之前触发)
       keypress(文本框变化之前触发)
       keyup
       如果按住不放,就会重复触发keydown和keypress
    
  • 键码

    发生keydown和keyup四,event对象的keyCode属性包含一个代码,对于键盘上的键。
    
  • textInput事件

    在可编辑区域中输入字符时,触发这个事件。只会在用户按下能够输入实际字符的键才会被触发。
    event对象中包含data属性,里面储存用户输入的字符
    
  • 复合事件

       用于处理IME(输入去编辑器)的输入序列。
       compositionstart
       compositionupdate
       compositionend
    
  • 触摸与手势事件

    • 触摸事件

      • touchstart,手指触摸屏幕时触发
      • touchmove,手指在屏幕滑动时连续触发
      • touchend,手指从屏幕上移开时触发
      • touchcancel,当系统停止跟踪触摸时触发
      • touches,表示当前跟着的触摸操作的Touch对象的数组
      • targetTouchs,特定事件目标的touch对象数组
      • changeTouches,

      上面的Touch对象数组都含有上面的坐标信息

    • 手势事件

      gesturestart,当一个手指一定按照屏幕上,而另一个手指由触摸屏幕时触发
      gesturechange,当触摸屏幕任何一个手指的位置发生变化的触发
      gestureend,当任何一个手指从屏幕上面移开时触发

内存和性能

添加到页面上的事件处理程序数量直接影响整体运行性能。
首先,每个函数都是对象,占用内存。其次,必须事先制定多余事件处理程序导致DOM访问次数增加,会延迟整个页面的交互就绪时间。

  • 事件委托

    利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。
    
  EventUtil.addHandler(item2,"click",function(event){
    
    
  	alert("I chaange the document`s title");	
  });

优点:

	  document对象可以很快访问,而且可以在页面声明周期热火时候为其添加事件处理程序
	  设置事件处理程序所需的事件更少。至天津一个事件处理程序所需的DOM引用更少,所花时间更少。
	  占用内存空间更少

猜你喜欢

转载自blog.csdn.net/ningpeixi679/article/details/113100258