Js高级程序设计第三版学习(十章)

                              Js高级程序设计第三版学习(十章)

 

 第十章 DOM 

DOM是针对HTML和XML文档的一个API(只接触html很少接触xml),DOM描绘了一个节点树,允许开发人员,添加,修改,删除,页面的一部分.

  1.节点层次:

节点分为几种不同的类型,每种节点都有各自的特性,方法,数据, 文档节点是每个文档的根节点, 文档元素(html) 是文档最外层的元素,每个文档只能有一个文档元素

HTML元素通过元素节点表示,特性通过特性节点表示,文档类型通过文档节点表示,所有节点类型都继承一个基类型

  • Node类型

所有节点类型都继承自Node类型,Node类型定义了12个字符常量,每个节点都有一个nodetype属性,nodetype属性必定与Node类型中的一个字符常量所对应

      if(ele.nodeType === Node.ELEMENT_NODE){
        console.log('是一个元素节点') //是一个元素节点
      }

      if(ele.nodeType === 1){
        console.log('是一个元素节点') //是一个元素节点
      }

由于低版本ie不公开Node构造函数, 所以为了兼容书中建议我们比较数字, 每个节点类型都有对应的数字

 每个节点都有一个childNodes属性, 这个属性保存了一个nodeList列表 该列表存放了子元素节点,nodeList列表是动态的,如果列表内部元素改变会反映到dom上,反之亦然. 虽然是list但是他并不是array的实例, 所以他只能被for循环迭代, 不能够被forEarch,for ..in,for... of迭代(会报错),

    <ul id="uuu">
      <li id="asd" class="ppap" data-nihao="nihao">1</li>
      <li id="dsa">1</li>
      <li>1</li>
      <li id="asd" class="ppap" data-nihao="nihao">1</li>
    </ul>
    <script>
      /* 
        要访问nodeList的节点 可以通过索引的形式,或者item()的形式都可以
        length属性记录的节点个数,
      */
      var ele = document.getElementById('uuu');
      console.log(ele.childNodes.length);//9
      console.log(ele.childNodes[0]);//#text
      console.log(ele.childNodes.item(0))//#text

      /*
        会报错!!
      for (const iterator of ele) {
        
      }
      ele.forEach(element => {
        
      }); 
      */
    </script>

值得注意的是childNodes中会保存空白的文本节点,而不仅仅是元素节点,这也是length等于9的原因, 每个节点都提供了一些属性用来访问关系节点,

      /* 
        parentNode获取父节点 , nextSibling下一个节点 没有返回null previousSibling上一个节点 没有返回null
      */
      var ele = document.getElementById('uuu');
      var asd = document.getElementById('asd');
      var firstChilddd = ele.childNodes[0];
      var lastChilddd = ele.childNodes[ele.childNodes.length - 1];
      console.log(firstChilddd.nextSibling);
      console.log(firstChilddd.previousSibling); //null
      console.log(firstChilddd.parentNode);
      console.log(lastChilddd.nextSibling); //null
      /* 
        如果要获取第一个节点或最后一个节点我们可以使用 firstChild或lastChild代替
      */
      console.log(firstChilddd === ele.firstChild); //true
      console.log(lastChilddd === ele.lastChild); //true

      /* 
      hasChildNodes 用来查询是否包含XX节点
    */
      console.log(ele.hasChildNodes(asd)); //true

对于节点的增删改..等等的方法

     /*
        parentNode获取父节点 , nextSibling下一个节点 没有返回null previousSibling上一个节点 没有返回null
      */
      var ele = document.getElementById('uuu');
      var asd = document.getElementById('asd');
      var im = document.getElementById('im');
      var firstChilddd = ele.childNodes[0];
      var lastChilddd = ele.childNodes[ele.childNodes.length - 1];

      // appendChild 在节点列表的末尾 添加节点
      //如果该节点是页面中存在的节点,那么这个节点就被添加到目标节点
      console.log(asd.appendChild(im)); //im

      /*
          insertBefore  插入节点, 如果第二参数为null 跟appendChild相同
          不为null 则在目标节点插入
      */
      console.log(ele.insertBefore(im, asd)); // im

      /* 
          replaceChild 替换节点 第一个参数 替换节点 第二个参数 被替换的节点
          返回被替换的节点
      */
      console.log(ele.replaceChild(im, asd)); //asd

      /* 
        removeChild 移除节点 返回被移除的节点,如果删除的是元素节点
        元素节点中包含文本节点,其实文本节点不会被删除,虽然不会在页面上显示
        但是其实依旧被父节点包含
        
      */
      console.log(ele.removeChild(im));//im

       /* 
        cloneAsd 克隆节点 参数为true为深克隆 连同子节点克隆
        无参数 为潜克隆 只可知节点本身
       */
      var asd = document.getElementById('asd');
      var cloneAsd = asd.cloneNode();
      console.log(cloneAsd);//浅
      var cloneAsd2 = asd.cloneNode(true);
      console.log(cloneAsd2);//深

      /* 
        normalize() 会清除空白节点, 
        会把相邻的文本节点,变成一个文本节点.
       */
      var asd = document.getElementById('asd');
      var text1 = document.createTextNode('文本1');
      var text2 = document.createTextNode('文本2');
      var text3 = document.createTextNode('文本3');
      asd.append(text1,text2,text3);
      console.log(asd.childNodes);//NodeList(12)
      asd.normalize();
      console.log(asd.childNodes);//NodeList(9)
  • Document类型

document对象是Document类型的实例, document代表整个html页面, document的子节点可以是 DocumentType(文档类型),Element(html节点),ProcessingInstroctior(不知道...),Comment(注释节点), document有两个快速访问子节点的属性, documentElement(html节点),documentBody(body节点)

如果存在文档声明(doctype) 那么doctype节点是第一个节点(ie11,chrome,ff),(与书上不同的是chrome不会把doctype加入nodeList中,但现在也会加入了), 如果存在注释,也会显示也会加入

document提供了一些网页信息的属性, tittle 文档标题 domain 域名 referrer 引用页的url URL 地址栏url

      console.log(document.title); //文档标题
      console.log(document.domain);// '' 域名
      console.log(document.referrer);// '' 链接到当前页面的那个页面的url
      console.log(document.URL);//地址栏的url

Dom1提供了三个方法来获取对象或对象集合, document.getElementById() 根据id查询, 返回单个对象,document.getElementsByTagName()根据标签名查找,返回一个动态集合HTMLCollection, 类似与nodeList,同样只能被for迭代,其他方式不行,同样可以通过item或索引的方式获取对象,但还有一个额外方法namedItem() 根据name值来获取对象,同时也支持按名称访问['xxxx'](但是只会获取第一个name为该字符串的对象),document.getElementsByName(''),根据name名查找,同样返回一个动态集合nodeList.

      var asd = document.getElementsByTagName('asd');
      console.log(asd);
      var pList = document.getElementsByTagName('p');
      console.log(pList); //HTMLCollection(4) [p, p, p, p, test: p]
      console.log(pList['test']); //  <p name="test">2</p>
      console.log(pList.namedItem('test')); // <p name="test">2</p>
      console.log(pList.item(0)); // <p name="test">2</p>
      console.log(pList[0]);// <p name="test">2</p>
      var testList = document.getElementsByName('test')
      console.log(testList) //NodeList(3) [p, p, p]

      //获取所有带name的a元素
      console.log(document.anchors)
      // 获取所有图片元素
      console.log(document.images)
      // 获取所有所有a元素
      console.log(document.links)
      //获取所有form元素
      console.log(document.forms)

document.wirte(), 页面写入, 如果在页面加载中使用会在文档末尾添加字段, 如果在页面加载之后使用会重写整个页面(正常也不会使用)

  • Element类型

Element用于表现html或xml的元素 , 元素名称可以用 tagName或nodeName获取

      var asd = document.getElementById('asd');
      console.log(asd.tagName)//LI

所有html元素都继承自HTMLElement类型,主要有id title className 这几个默认属性, 我们直接用属性的方式获取,也可以用getAttribute(),setAttribute();removeAttribute(),对属性进行增删改查

      //获取元素
      var asd = document.getElementById('asd');
      //元素的标签名
      console.log(asd.tagName); //LI
      //元素的class
      console.log(asd.className);//ppap
      //元素的id
      console.log(asd.id);//asd
      //更改元素的className
      asd.className = 'aaaa';

      //获取元素特性 如果没有返回null
      var className1 = asd.getAttribute('class');
      console.log(className1); //aaaa
      var className2 = asd.getAttribute('asdhkasdhjk');
      console.log(className2); // null

      //设置元素的特性 如果是不存在的特性那么就新建一个添加 否则直接更改
      asd.setAttribute('lalal','asdasdasd');

      //移除元素属性
      asd.removeAttribute('lalal');

在获取行内样式和元素的方法时, 这两种方式会有差别,但在正常项目其实还是使用属性获取特性的方式居多,get方式用于获取自定义属性居多

      // 在获取元素的样式时 通过getAttribute 返回标签内style的属性,没有为null ,而用属性方式获取返回的是对象
      console.log(asd.getAttribute('style')) // background:#ffcc00
      console.log(asd.style);//CSSStyleDeclaration 


      // 在获取元素的事件时 通过getAttribute或属性获取返回的值是不同的
      // 如果元素标签内未绑定事件 getAttribute返回null 而用属性方式不管是标签绑定还是代码绑定都可以获取
      console.log(asd.getAttribute('onclick')) //console.log('asd')
      console.log(asd.onclick) //ƒ onclick(event) {console.log('asd')}

Element元素提供了attributes属性 是一个NamedNodeMap集合类似Nodelist,也提供了增删改查的方法,但并不常用

      //获取元素
      var asd = document.getElementById('asd');

      /* 
        getNamedItem 根据特性名获取特性 格式class="ppap"
        setNamedItem 设置特性, 只能是attr节点
        可以通过nodeValue 获取特性值
        也可以通过索引或者item()的形式获取特性,不过不同浏览器顺序可能不同
        removeNamedItem 移除特性
       */
      console.log(asd.attributes.getNamedItem('class')); // class="ppap"
      console.log(asd.attributes.getNamedItem('class').nodeValue); // ppap
      var att = document.createAttribute('asdsad');
      att.nodeValue ='asdjkashdkj'
      asd.attributes.setNamedItem(att);
      console.log(asd.attributes.item(0));//id="asd"
      console.log(asd.attributes['data-nihao'].nodeValue);//nihao
      console.log(asd.attributes.removeNamedItem('data-nihao'));//data-nihao="nihao"

Element提供了创建元素的方法 我们也可以通过dom查询方法来查询element节点的后代节点

      //获取元素
      var asd = document.getElementById('asd');

      /* 
        createElement,用来创建Element元素,但元素需要结合append添加到页面中
       */
      var div = document.createElement('div');
      div.innerText = 'ppap';
      asd.appendChild(div);

      /* 
        如果我们获取一个节点,但是还想要获取指定的后代元素可以使用 查询方法
        就会获取后代节点了
       */
      var spanList = asd.getElementsByTagName('span');
      console.log(spanList); //HTMLCollection [span.sadas]
  • Text类型

Text类型表示可以按照字面解释的纯文本内容,text没有子节点,相邻两个文本节点没有空格

    <script>
      //获取元素
      var asd = document.getElementById('asd');

      //创建文本节点 元素节点添加文本节点
      var text=  document.createTextNode('text');
      asd.appendChild(text);

      //文本节点的值 可以通过nodeValue获取
      var textContent = asd.childNodes[3].nodeValue;
      console.log(textContent); //text

      //文本节点添加文本节点
      text.appendData('append')
      //console.log(text)//textappend

      //删除文本,从指定位置删,第二个参数多少个字符
      text.deleteData(2,3)//teppend
      //从指定位置插入文本
      text.insertData(2,'hehe')//teheheppend
      //从指定位置替换 替换两个字符 替换文本
      text.replaceData(3,2,'dada')//tehdadaeppend
      //从指定位置分割文本节点, 会分割成两个文本节点 返回后一个节点
      console.log(text.splitText(5).nodeValue)//daeppend
      //从指定位置截取字符串 第二个参数截取个数
      console.log(text.substringData(0,4));//tehd
    </script>
  • Comment类型

注释节点跟文本节点继承于一个基类, 所以我们可以用操作文本节点的方式去操作注释节点,创建注释节点用document.createComment()方法

  • DocumentType类型

文档类型, 一般都放在document.doctype中 document.doctype.name 记录了<! doctype 后面的内容

  • Attr类型

Attr类型 表示元素的特性, 特性就是存在于 attributes中的节点, 但是它并不属于Dom文档树的一部分

     var asd = document.getElementById('asd');
     var att = document.createAttribute('data-ppap');
     att.nodeValue = 'hehe'
     asd.attributes.setNamedItem(att);

  2.DOM操作技术:

  • 使用nodeList

所有的动态集合(nodeList,HTMLCollection,NameNodeMap)都是都是实时查询的,在我们迭代nodelist的时候如果用nodeList.length进行比较是有可能造成死循环的

      var liList = document.getElementsByTagName('li')
      for (let index = 0; index < liList.length; index++) {        
        document.body.appendChild(document.createElement('li')) //死循环
      }

书中建议我们在进行是迭代时,再创建一个变量来存储list.length(类似快照),然后让循环条件跟这个变量比较, 同时我们应该尽量减少访问nodeList的次数,每运行一次都会对文档进行查询

      var liList = document.getElementsByTagName('li')
      for (let index = 0,llength = liList.length; index < llength; index++) {        
        document.body.appendChild(document.createElement('li'))
      }

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值