前端JavaScript

复习笔记之API(3) 节点

2020-04-13  本文已影响0人  晚月川

操作元素补充

element.属性element.getAttribute('属性')两种方法的区别:

  • element.属性:获取内置属性值(元素本身自带的属性)
  • element.getAttribute('属性'):主要获得自定义属性(标准)

element.属性= '值'element.setAttribute('属性', '值');的区别

  • element.属性= '值' 设置内置属性值
  • element.setAttribute('属性', '值');主要针对于自定义属性(标准)

H5自定义属性

  • 自定义属性的目的:是为了保存并使用数据,有些数据可以保存到页面中而不用保存到数据库中
  • 问题:有些自定义属性很容易引起歧义,不容易判断是元素内置属性还是自定义属性

H5规定自定义属性data-开头做属性名并且赋值;例如:<div data-index="1"></div>;使用JS设置element.setAttribute('data-index', 2)

<div getTime="20" data-index="1"></div>
<script>
    let div = document.querySelector('div');
    // console.log('div.getTime'); //=>undefined
    console.log(div.getAttribute('getTime')); //=>20
    div.setAttribute('data-time', 20);
</script>
<div data-time="20" data-index="1" data-list-name="andy"></div>
<script>
    let div = document.querySelector('div');
    // 兼容性获取
    console.log(div.getAttribute('data-index'));
    console.log(div.getAttribute('data-list-name'));
    // H5新增的获取自定义属性的方法
    console.log(div.dataset.index);
    // dataset是一个集合,里面存放了所有以data-开头的自定义属性
    console.log(div.dataset);
    console.log(div.dataset.index);
    console.log(div.dataset['index']);
    // 如果自定义属性里面有多个-链接的单词,我们获取的时候采用驼峰命名法
    console.log(div.dataset.listName); //=>andy
    console.log(div.dataset['listName']); //=>andy
</script>

节点操作

节点概述

网页中所有的内容都是节点(标签、属性、文本、注释等),在DOM中,节点使用node来表示。DOM树种的所有节点均可通过JavaScript进行访问,所有HTML元素(节点)均可被修改、创建或删除。

  • 一般情况下,节点至少拥有nodeType(节点类型)、nideNae(节点名称)和nodeValue(节点值)这三个基本属性
    • 元素节点nodeType为1(实际开发中主要操作元素节点)
    • 属性节点nodeType为2
    • 文本节点nodeType为3(文本节点包括文字、空格、换行等)

节点层级

利用DOM树可以把节点划分为不同的层级关系,常见的是父子兄弟层级(API第一章有DOM树简图)

  • 父级节点parentNode
    • 得到的是离元素最近的父级节点,如果找不到父级节点就返回为null
<div class="demo">
    <div class="box">
        <span class="erweima"></span>
    </div>
</div>
<script>
    let erweima = document.querySelector('.erweima');
    // 得到的是离元素最近的父级节点,如果找不到父级节点就返回为null
    console.log(erweima.parentNode);
</script>
  • 子节点childNodes(标准)
    • 返回包含指定节点的子节点的集合,该集合为即时更新的集合
<ul>
    <li>第1个</li>
    <li>第2个</li>
    <li>第3个</li>
</ul>
<script>
    let ul = document.querySelector('ul'),
        lis = ul.querySelectorAll('li');
    // 子节点
    console.log(ul.childNodes); //=>获得ul下面的所有子节点(包括元素节点和文本节点等)
</script>

如果只想获得里面的元素节点,则需要专门处理,所以一般不用element.childNodes

let ul = document.querySelector('ul');
for(let i = 0; i < ul.childNodes.length; i++) {
    if(ul.childNodes[i].nodeType === 1) {
        // ul.childNodes[i]是元素节点
        console.log(ul.childNodes[i]);
    }
}

element.children(非标准)获取元素子节点

console.log(ul.children);
  • element.firstChild获取元素的第一个子节点(找不到则返回null,也是包含所有节点)
  • element.lastChild获取元素的最后一个子节点(找不到则返回null,也是包含所有节点)
  • element.firstElementChild返回第一个子元素节点,找不到则返回null(兼容性问题:IE9以上支持)
  • element.lastElementChild返回最后一个子元素节点,找不到则返回null(兼容性问题:IE9以上支持)
<ul>
    <li>第1个</li>
    <li>第2个</li>
    <li>第3个</li>
</ul>
<script>
    let ul = document.querySelector('ul');
    // firstChild 第一个子节点,不管是元素节点还是文本节点
    console.log('ul.firstChild');
    console.log('ul.lastChild');
    // 只返回元素节点,找不到返回null
    console.log('ul.firstElementChild');
    console.log('ul.lastElementChild');
    // 实际开发中的写法
    console.log(ul.children[0]);
    console.log(ul.children[ul.children.length - 1]);
</script>

节点层级里面的兄弟节点

  • nextSibling返回当前元素的下一个弟弟节点,找不到则返回null,同样,也会包含所有的节点
  • previousSibling返回当前元素的上一个哥哥节点,找不到则返回null,同样,也会包含所有的节点
  • nextElementSibling返回当前元素的下一个弟弟元素节点,找不到返回null(兼容性问题:IE9以上支持)
  • previousElementSibling返回当前元素的上一个哥哥元素节点,找不到返回null(兼容性问题:IE9以上支持)
<h2>嘿嘿</h2>
<div>呵呵</div>
<span>哈哈</span>
<script>
    let div = document.querySelector('div');
    console.log(div.nextSibling);
    console.log(div.previousSibling);
    console.log(div.nextElementSibling);
    console.log(div.previousElementSibling);
</script>

=================
处理nextElementSiblingpreviousElementSibling兼容性问题

// 弟弟节点
function getNextElementSibling(element) {
    let el = element;
    while (el = el.nextSibling) {
        if (el.nodeType === 1) {
            return el;
        }
    }
    return null;
}
// 哥哥节点
function getPreviousElementSibling(element) {
    let el = element;
    while (el = el.previousSibling) {
        if (el.nodeType === 1) {
            return el;
        }
    }
    return null;
}

创建节点&&添加节点

  • document.createElement('tagName')方法创建由tagName指定的HTML元素。因为这些元素原先不存在,是根据我们的需求动态生成的,所以也被称为动态创建元素节点
  • node.appendChild(child)方法将一个节点添加到指定父节点的子节点列表末尾。类似于CSS里面的after伪元素
<!-- 在ul里面添加一个li -->
<ul>
    <li>123</li>
</ul>
<script>
    // 创建节点元素
    let li = document.createElement('li');
    // 添加节点 node.appendChild(child)  node 父级  child 子级
    // 在父级节点的末尾追加元素,类似于数组中的push
    let ul = document.querySelector('ul');
    ul.appendChild(li);
</script>
  • node.insertBefore(child, 指定元素)方法将一个节点添加到父节点的指定子节点的前面。类似于CSS里面的before伪元素
<ul>
    <li>123</li>
</ul>
<script>
    let ul = document.querySelector('ul'),
        li = document.createElement('li');
    ul.insertBefore(li, ul.children[0]);
</script>

在页面中添加元素分为两步:创建元素和添加元素

删除节点

node.removeChild()方法从DOM中删除一个子节点,返回删除的节点

<button>删除</button>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
<script>
    let ul = document.querySelector('ul'),
        btn = document.querySelector('button');
    btn.onclick = function() {
        if(ul.children.length == 0){
            this.disabled == true;
            alert('已经都被你消灭了')
        }else{
            ul.removeChild(ul.children[0]);
        }
    }
</script>

复制节点(克隆节点)

node.cloneNode()方法返回调用该方法的节点的一个副本,也成为克隆节点/拷贝节点

<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
</ul>
<script>
    let ul = document.querySelector('ul');
    let obj =  ul.children[0].cloneNode();
    // let obj =  ul.children[0].cloneNode(true);
    ul.appendChild(obj);
</script>
  • 如果括号里面的参数为或者为false,则是浅拷贝(只复制节点本身,不克隆里面的子节点)
  • 如果括号里面的参数为true,则是深拷贝(复制节点本身以及里面的子节点)
上一篇下一篇

猜你喜欢

热点阅读