• DOM基础知识


    DOM基础知识(不包括DOM事件)


    DOM简介

    DOM针对html和xml文档的一个API(应用程序接口),DOM描绘了一个层次化的节点树,允许开发人员添加、移动、修改页面的一部分内容。注意:IE中所有DOM对象是以COM对象形式实现的,其与原生Javascript中的DOM有所差异

    DOM的具体内容

    1、DOM节点层次

    1.1Node类型

    DOM将html描绘成一个多层次节点的结构,节点分为不同的类型,每种类型分别表示文档中不同的信息及标记,每个节点都拥有各自的特点,数据和方法,节点和节点之间存在着关系,从而形成关系网。文档节点是每个文档的根节点,<html>为整个html文档的文档元素.。

    DOM0级定义一个Node接口,该接口将由DOM中的所有节点类型实现,在js中为Node类型实现。

    nodeType属性:每个节点都有这个属性,用于表明节点的类型,由1—12个数值常量表示,常用元素节点为1,文本节点为3

    nodeName属性:保存的始终是元素的标签名的大写;nodeValue属性:元素节点始终为null,文本节点为文本,attribute类型为特性的值

    childNodes属性:每个节点都存在,其中保存着一个NodeList对象,NodeList是一种类数组对象,用于保存一组有序的节点,通过位置访问节点,length表示节点的数量。注意:nodeList不是数组实例,实际是基于DOM结构动态执行查询的结果,DOM的变化能够直接的反应在NodeList对象之下。有呼吸,有生命的对象。

    firstChild:第一个节点;lastChild:最后一个节点

    parentNode属性:表示父节点,每个节点都存在,指向文档树中的父节点

    nextSibling属性:表示下一个同胞节点,最后一个节点的nextSibling为null;previousSibling属性:表示上一个同胞节点,第一个节点的previousSibling为null;没有同胞节点则都为null

    ownerDocument属性:每个节点都存在,直接指向整个文档的文档节点即<html>,,表示这个节点只存在于这个文档之中,不能同时存在多个文件中

    操作某节点的子节点

    appendChild()方法:用于向childNodes节点后添加一个节点,节点添加后原来的关系指针都会相应的更新;

    insertBefore()方法:用于向childNodes节点前添加一个节点,接受两个参数,为要插入的节点和参照的节点,

    注意:如果该节点已经存在,那么该节点将从原来位置转移到新的位置;两个方法都是在父节点上操作的;

    replaceChild()方法:用于替换节点,接受两个参数,为要插入的节点和要替换的节点。(技术上原先的节点还存在,只是所有关系指针被替换的节点复制一遍,实际上文档中已经没有其位置)

    removeChild() 方法:用于移除节点,接受一个参数,为要移除的节点,这也是其的返回值(同样,该节点在文档中没有位置)

    其他操作方法

    cloneNode()方法:用于创建调用这个方法的节点的完全相同副本,接受一个布尔值的参数,表示是否深复制,true表示深复制,复制节点及整个子节点树,false表示浅复制,复制仅仅这个节点。这个方法不会复制添加到DOM节点中的js属性,只复制特性、(子节点)、其他一切不会复制。

    normalize()方法:处理文档树中的文本节点,由于解析器的实现或DOM操作的原因,可能会出现文本节点不包文本,文本出现两次等情况,调用此方法就会在后代查找空文本节点删除,在创建文本节点细说

    1.2Document类型

    文档子节点

    js通过document类型表示文档,浏览器中document的对象是HTMLDocument的一个实例,表示整个HTML页面,同时,document也是window对象的一个属性,可以作为全局对象访问

    文档子节点的获取即html的获取可以通过document.doucmentElement或者document.childNodes[0]、document.firstChild

    document.body直接指向<body>元素,document.doctype直接指向文档说明(浏览器的支持差别大)

    document.title直接指向<title>元素,document.URL,指向页面完整的URL,document.domain,指向域名,document.referrer,指向来源页面的URL

    查找元素

    document提供两种方法获得元素

    1、document.getElementById(id),id必须和元素的id特性(attr)严格匹配,有则返回i该元素,没有则返回null

    2、document.getElementsByTagName(标签名),有则返回的是包含零或多个元素的NodeList,而在HTML文档中,会返回一个HTMLCollection对象,作为一个“动态”集合,跟NodeList相似,也有length值。同时,HTMLCollection有个namedItem()方法,可以用索引值表示比如,另外document.getElementsByTagName("*"),获取的所有的元素,返回的是HTMLCollection

    <img src="dog.jpeg" name="imgDog"></img>
    var images=document.getElementsByTagName("img")
    var dog=images.namedItem("imDog")
    或者是
    var dog=images["imDog"]

    3、document.getElementsByName(),只有HTMLDocument类型才有的方法,一般取得单选按钮比如,这个也会返回一个NodeList

    <fieldset>
       <legend>your color</legend>
       <ul>
         <li><input type="radio" value="red" name="color" id="colorRed" checked>red</li>   这里的name值都一样
         <li><input type="radio" value="yellow" name="color" id="colorYellow">yellow</li>
         <li><input type="radio" value="olive" name="color" id="colorOlive">olive</li>
       </ul>
    </fieldset>

    var radios=document.getElementsByName("color")

    4、其他一些特殊集合,比如document.anchors,document.form,document.links等等不常用

    5、DOM一致性检测,DOM分为多级,检测浏览器的类型十分必要,通过document.implementation属性检测,DOM1级通过hasFeature()检测,最好还要通过能力检测方可使用一些不确定的DOM级别用法,具体如下

    document.implementation.hasFeature("xml","1.0") 返回的是布尔值,最好通过能力检测

    文档写入

    document.write("<strong>"+这是加粗+"</strong>")

    document.writeln("<strong>"+这是加粗+"</strong>")这个会在字符串末尾添加换行符

    document.close()和document.open()关闭和打开

    1.3Element类型

    对于element类型,nodeName和tagName是一样的,都返回标签名

    取得特性

    每个元素都有一个或多个特性,用途在于给相应元素或其内容的附加信息

    getAttribute("attr"),这里的attr可以是id,class,title,lang,dir等等,对于style和onclick这两个特性,由于通过特性和属性访问存在差异,一般不用getAttribute(),一般获取自定义特性时候

    <div id="div1" class="div1" title="div" data-value="define"></div>
    alert(div.getAttribute(data-value))获得自定义的特性,自定义特性加个data-前缀便于浏览器渲染

    设置特性

    通过setAttribute("attr","value")来设置特性,如果特性存在则会替换原来特性;通过removeAttribute()直接移除特性

    div.mycolor="red"
    alert(div.getAttribute("mycolor"))返回的是null除了IE,添加自定义属性是不同于设置特性的

    Attribute属性

    element类型是DOM中唯一支持attribute属性的类型,attribute中包含一个NamedNodeMap,和NodeList相似,也是个动态集合,每一个节点都保存在NamedNodeMap中,一些方法就不介绍,不常用,大多用用这个来遍历元素的特性,比如

    function outputAttribute(element){
    var pairs=new Array(),attrName,attrValue,i,len;
    for(i=0;i<element.attribute.length;i++){
    attrName=element.attribute[i].nodeName; 注意:这里的nodeName和nodeValue是attribute的属性,可不是element的属性
    attrValue=element.attribute[i].nodeValue;
    pairs.push(attrName+"=""+attrValue+""")
    }
    return pairs.join(" ")
    }

    补充attr类型,nodeName为特性名称,nodeValue为特性值,不被认为是DOM文档树一部分,尽管也是节点,attr有三个属性为name,value,specified(布尔值,区别特性是指定还是默认),使用document.createAttribute()传入特性名称就可创建特性节点比如

    var div=getElementById("div")                事实上这里的name就是setAttribute的nodeName   value就是setAttribute的nodeValue   
    var attr=document.createAttribute("title")
    attr.value="这是attr的value值"
    div.setAttributeNode(attr)
    alert(div.title) 弹出 这是attr的value值

    创建元素

    通过document.createElement(标签名)创建元素的标签,同时也为其设置了ownerDocument属性,通过appendChild,insertBefore,replaceChild等等将其添加到文档树中

    newli=document.createElement("li")
    newli.innerHTML="新创建的li"
    ul.appendChild("newli")

    元素的子节点

    由于各个浏览器的差异,导致元素中的子节点由于空白字符的原因都是不一样的,当用childNodes遍历整个子节点时,由于浏览器的差别所以一般会判断nodeType属性

    for(var i=0,len=element.childNodes.length;i<len;i++){
    if(element.childNodes[i].nodeType==1){ 通过nodeType筛选出元素标签
    //执行操作
    }
    }

    元素遍历(Element Traversal)为其规范几个新的属性(兼容性问题有待商量)

    childElementCount   firstElementChild    lastElementChild   previousElementSibling   nextElementSibling

    var i,len,child=element.firstElementChild;
    while(child!=element.lastElementChild){
    processChild(child)
    child=child.nextElementSibling
    }

    1.4Text类型

    nodeType为3,nodeValue为节点包含的文本,没有内容就没有文本节点,有内容或空格都是一个文本节点即它的length,可以通过nodeValue和data来访问text节点的文本

    创建文本节点

    通过document.createTextNode(文本)创建新的文本节点,接受一个参数即要插入的文本

    var div=document.createElement("div")
    var text=document.createTextNode("这是一段新的文本")
    div.appendChild(text)
    document.body.appendChild(div)

    规范化文本节点

    一般情况下,每个元素只有一个文本节点,当出现多个文本节点时,文本就会连在一起,不会出现空格,用前面所说的在父节点上使用normalize()方法,

    var div=document.createElement("div")
    var textone=document.createTextNode("hello world")
    var texttwo=document.createTextNode("lishuangshuang")
    div.appendChild(textone)
    div.appendChild(texttwo)
    document.body.appendChild(div)
    alert(div.childNodes.length) 此时为2
    div.normalize()
    alert(div.childNodes.length) 此时为1
    alert(div.childNodes[0].nodeValue) 出现hello world lishaungshuang

    分割文本节点

    是一种从文本节点中提取数据的常用DOM解析技术,一般为splitText(数值)方法,将nodeValue分成连个文本节点

    var div=document.createElement("div")
    var textone=document.createTextNode("helloaworld")
    div.appendChild(textone)
    document.body.appendChild(div)
    var newNode=div.firstChild.splitText(5)
    alert(div.firstChild.nodeValue) 为hello
    alert(newNode.nodeValue) 为aworld 这里的newNode就是div.childNodes[1]
    alert(div.childNodes.length) 为2

    1.5Comment类型

    注释在DOM通过Comment类型表示,nodeValue就是注释的内容

    1.6CDATASection类型

    只针对xml文档,表示CDATA区域,多数浏览器会把其错误当作Comment或者Element,在xml文档中直接document.createCDataSection()创建CDATA区域

    1.7CDATASection类型(不常用)

    1.8DocumentFragment类型(文档片段)

    nodeValue为null,直接document.createDocumentFragment()方法创建文档片段

    var fragment=document.createDocumentFragment
    var ul=document.getElementById("ul")
    var li=null
    for(var i=0;i<3;i++){
    li=document.createElement("li")
    li.appendChild(document.createTextNode("Item"+(i+1)))
    fragment.appendChild(li) 先放在fragment中
    }
    ul.appendChild(fragment) 文档片段已删除并转移到ul里面了,避免了每一个浏览器反复渲染新信息

    2、DOM操作技术

     1动态脚本

    这里的动态脚本指的是页面加载不存在时,但将来某一时刻通过修改DOM动态添加的脚本

    var script=createELement("script")
    script.type="text/javascript"
    script.url="client.js"
    document.body.appendChild(script)


    function loadScriptString(code){
    var script=document.createElement("script")
    script.type="text/javascript"
    try{
    script.appendChild(document.createTextNode(code))
    }catch(ex){
    script.text=code 兼容IE
    }
    document.body.appendChild(script)
    }
    loadScriptString("function(){alert('hello world')}")

    2动态样式

    function loadStyle(url){
    var link=document.createElement("link")
    link.rel="stylesheet"
    link.type="text/css"
    link.href=url
    var head=document.getElementsByTagName("head")[0]
    head.appendChild(link)
    }
    loadStyle("client.css")
      

    function loadstyleString(css){
    var style=document.createElement("style")
    css.type="text/css"
    try{
    style.appendChild(document.createTextNode(css))
    }catch(ex){
    style.stylesheet.cssText=css
    }
    var head=document.getELementsByTagName("head")[0]
    head.appendChild(style)
    }
    loadstyleString("body{background:red;}")

     3操作表格

     原来的操作表格十分复杂比如

    创建table
    var table=document.createElement("table")
    table.border=1
    table.width="100%"
    创建tbody
    var tbody=document.createElement("tbody")
    table.appendChild(tbody)
    创建tr和td
    var row1=document.createElement("row")
    tbody.appendChild(row1)
    var cell1=document.createElement("td")
    cell1.appendChild(document.createTextNode("cell_1"))
    row1.appendChild(cell1)
    var cell2=document.createElement("td")
    cell2.appendChild(document.createTextNode("cell_2"))
    row1.appendChild(cell2)
    添加到body中
    document.body.appendChild(table)

    table有一些属性

    tBodies是一个<tbody>元素的HTMLCollection

    tHead保存着对<thead>元素的指针

    tFoot保存着对<tfoot>元素的指针

    rows是表格中所有行的HTMLCollection

    cells是表格中所有行的单元格的HTMLCollection

    table有一些方法

    deleteRow(pos)删除指定位置的行

    insertRow(pos)在指定位置插入行,并返回该行

    deleteCell(pos)  insertCell(pos)同理

    创建table
    var table=document.createElement("table")
    table.border=1
    table.width="100%"
    创建tbody
    var tbody=document.createElement("tbody")
    table.appendChild(tbody)
    创建行和列
    tbody.insertRow(0)
    tbody.row[0].insertCell(0)
    tbody.row[0].cells[0].appendChild(document.createTextNode("cell1"))
    tbody.row[0].insertCell(1)
    tbody.row[0].cells[1].appendChild(document.createTextNode("cell2"))
    添加到body中
    document.body.appendChild(table)

    4使用NodeList

    NodeList和NamedNodeMap和HTMLCollection都是动态的,每当文档结构发生变化时,都会得到更新,始终保持最新,最准确的信息,本质上说,所有的NodeList对象都是在访问DOM文档时实时运行的查询

    var divs=document.getElementsByTagName("div"),i,div;
    for(i=0;i<divs.length;i++){ //因为len是实时变化的,所以循环下去
    div=document.createElement("div")
    document.body.appendChild(div)
    }


    var divs=document.getElementsByTagName("div"),i,len,div;
    for(i=0,len=divs.length;i++){ //这里的len已经初始化过,相当于保存一开始的快照,从而避免
    div=document.createElement("div")
    document.body.appendChild(div)
    }
    一般来说,尽量减少访问NodeList的次数,每次访问NodeList都会运行一次基于文档的查询,考虑先缓存一下

     基础不牢,地动山摇

  • 相关阅读:
    ASP.NET Core 2.1 Web API + Identity Server 4 + Angular 6 + Angular Material 实战小项目视频
    .NET Core TDD 前传: 编写易于测试的代码 -- 单一职责
    学习Identity Server 4的预备知识 (误删, 重补)
    .NET Core TDD 前传: 编写易于测试的代码 -- 全局状态
    .NET Core TDD 前传: 编写易于测试的代码 -- 依赖项
    .NET Core TDD 前传: 编写易于测试的代码 -- 构建对象
    .NET Core TDD 前传: 编写易于测试的代码 -- 缝
    SpringBoot入门教程(十)应用监控Actuator
    SpringBoot入门教程(九)定时任务Schedule
    SpringBoot入门教程(八)配置logback日志
  • 原文地址:https://www.cnblogs.com/iDouble/p/8288352.html
Copyright © 2020-2023  润新知