DOM专题

84 篇文章 3 订阅

javascript 的组成部分

  • - DOM (document object model) 文档对象模型
  • - BOM (browers object model) 浏览器对象模型
  • - ECMAScript js 的核心

DOM树:

1.DOM 节点

1.1节点分类

  • - 元素节点:每个 HTML元素  
  • - 属性节点:HTML元素的属性
  • - 文本节点:HTML元素内的文本 。换行在,文档解析时会解析成空白符,所以属于文本节点
  • - 注释节点:注释 <!---->
  • - 文档节点:整个文档document 
<body>
<ul id="list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
<script>
{
    let list = document.querySelector("#list");
    //发现li之前和li之间的换行,都是一个文本节点
    // console.log(list.childNodes);//NodeList(11) [text, li, text, li, text, li, text, li, text, li, text]

    //发现document下有两个子节点,文档声明也是一个子节点
    console.log(document.childNodes);//NodeList(2) [html, html]
    
}
</script>
</body>

1.2常用节点类型 --- nodeType

  • - 元素节点:1  
  • - 属性节点:2
  • - 文本节点:3  
  • - 注释节点:8
  • - 文档节点:9
  • -文档声明节点:10

1.3节点名称 --- nodeName

  • - 元素节点:标签名大写
  • - 文本节点:为#text 
  • - 注释节点:为#comment
  • - 文档节点:为#document
  • 文档声明节点:为 html
<body>
<ul id="list">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>
        <span>span1</span>
        <span>span2</span>
    </li>
    <!-- 这是一条注释 -->
    <li>5</li>
</ul>
<script>
{
    let list = document.querySelector("#list");
    console.log(document.nodeType,document.nodeName);//9 文档节点 "#document"
    
    //发现:document根节点下有两个节点,1 元素节点,节点名称元素标签名大写;10 文档声明节点 节点名称 HTML
    document.childNodes.forEach(item=>{
        console.log(item.nodeType,item.nodeName);
    });

    //3 文本节点 #text;8 注释节点 #comment
    list.childNodes.forEach(item=>{
        console.log(item.nodeType,item.nodeName);
    });
}
</script>
</body>

 

2.DOM关系

父子级关系;兄弟级关系

2.1查找子级:

getElementsByTagName/ByClassName,quarySelector/quarySelectorAll()等方法都是查找子级,但会把子级和孙子级也查找出来

  • - childNodes 子节点:包括所有节点(文本节点、注释节点、元素节点......)。返回类型为NodeList
<div id="wrap">
    <p>p1</p>
    <p>p2</p>
    <!-- 注释 -->
    <h3>h2</h3>
    <p>p3</p>
    <p>p4</p>
    <h3>h2</h3>
    <p>p5</p>
    <h3>h2</h3>
    <p>p6</p>
</div>
<script>
{
    let wrap = document.querySelector("#wrap");
    //childNodes获取到所有子节点(包括所有子节点:包括文本节点、元素节点、注释节点...)
    console.log(wrap.childNodes);//NodeList(21) [text, p, text, p, text, comment, text, h3, text, p, text, p, text, h3, text, p, text, h3, text, p, text]

    //要使用childNodes获取到所有子级元素节点(使用过滤方法,当nodeType == 1时返回)
    let childrens = wrap.childNodes;
    childrens = [...childrens].filter(item => item.nodeType == 1 );
    console.log(childrens);//(9) [p, p, h3, p, p, h3, p, h3, p]成功过滤出所有的元素节点
    
}
</script>
</body>
  • - children 子元素:只包含元素节点。返回类型为HTMLCollection
    let wrap = document.querySelector("#wrap");
    //children获取到所有元素
    console.log(wrap.children);//HTMLCollection(9) [p, p, h3, p, p, h3, p, h3, p]
  • - firstChild 第0个子节点
  • - firstElementChild 第0个子元素
  • - lastChild 最后一个子节点
  • - lastElementChild 最后一个子元素
    let wrap = document.querySelector("#wrap");
    console.log(wrap.firstChild,wrap.firstElementChild);//#text  <p>p1</p>
    console.log(wrap.lastChild,wrap.lastElementChild);//#text  <p>p6</p>

2.2查找兄弟级:

  • - nextSibling 下一个兄弟节点
  • - nextElementSibling 下一个兄弟元素
  • - previousSibling 上一个兄弟节点
  • - previousElementSibling 上一个兄弟元素
    let wrap = document.querySelector("#wrap");
    let h2 = wrap.children[2];
    console.log(h2);//<h3>h2</h3>
    
    console.log(h2.nextSibling,h2.nextElementSibling);//#text h3前换行 <p>p3</p>
    console.log(h2.previousSibling,h2.previousElementSibling);//#text p3前换行 <p>p2</p>

2.3查找父级:

  • - parentNode 父节点  ,获取父节点和父元素没有任何区别,因为本身只有元素才可以有子级,所以父级一点会是一个元素
  • - parentElement 父元素
  • - offsetParent 定位父级。元素根据定位的父级进行获取,如果有定位父级就是定位父级,没有定位父级,就是该元素的父级
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #box {
            position: relative;
        }
        span {
            position: absolute;
            display: block;
            width: 200px;
            height: 200px;
        }
    </style>
</head>
<body>
<div id="box">
    <div id="box2">
        <span></span>
    </div>
</div>
<script>
{
    /*
    - parentNode 父节点  ,获取父节点和父元素没有任何区别,因为本身只有元素才可以有子级,所以父级一点会是一个元素
    - parentElement 父元素
    - offsetParent 定位父级。元素根据定位的父级进行获取,如果有定位父级就是定位父级,没有定位父级,就是该元素的父级
    */
    let span = document.querySelector("span");
    console.log(span.parentElement,span.parentNode);//都是box2

    //定位父级  
    console.log(span.offsetParent);//因为span的定位父级是box,所以offsetParent获取到的父级是box;如果没有设置,其父级就是box2
      
}
</script>
</body>
</html>

2.4NodeList 和 HTMLCollection的区别 

获取元素得到值为NodeList:

  • childNodes
  • querySelectorAll()

获取元素得到值为HTMLCollection:

  • children;
  • getElementsByTagName
  • getElementsByClassName
  1. NodeList可以使用forEach方法,但是HTMLCollection不能使用forEach方法;
  2. HTMLCollection每次调用都会进行动态获取;虽然NodeList的childNodes可以进行动态获取,但NodeList的querySelectorAll不能进行动态获取,需要手动进行更新;
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<div id="box">
    <p class="pAll"></p>
    <p class="pAll"></p>
    <p class="pAll"></p>
</div>
<script>
{
    let box = document.querySelector("#box");
    let childNode = box.childNodes;
    console.log(childNode);//NodeList(7) [text, p.pAll, text, p.pAll, text, p.pAll, text]
    let qsAll = box.querySelectorAll("p");
    console.log(qsAll);//NodeList(3) [p.pAll, p.pAll, p.pAll]

    let eBClass = box.getElementsByClassName("pAll");
    console.log(eBClass);//HTMLCollection(3) [p.pAll, p.pAll, p.pAll]

    let eBTagName = box.getElementsByTagName("p");
    console.log(eBTagName);//HTMLCollection(3) [p.pAll, p.pAll, p.pAll]

    let childs = box.children;

    console.log("动态获取-----------------");
    //所有HTMLCollection的都可以进行动态获取
    box.innerHTML = '';
    console.log(qsAll);// querySelectorAll里面的P标签并没有被清空NodeList(3) [p.pAll, p.pAll, p.pAll]
    //只有重新进行querySelectorAll手动获取才能动态更新
    console.log(box.querySelectorAll("p"));//手动获取后得到的是被清空后的内容NodeList []

    //childNodes、getElementsByClassName、getElementsByTagName都会进行自动动态获取
    console.log(childNode);//NodeList []
    console.log(eBClass);//HTMLCollection []
    console.log(eBTagName);//HTMLCollection []
    

}
</script>
</body>
</html>

3.DOM 属性操作

注意 . 和 [] 都是 ECMAScript 中,对象的属性操作,对象属性的值会被存在内存中, 想要直接获取存在 文档中属性,或者 想把一个属性设置在文档中我们需要使用DOM 的属性操作

合法属性:w3c规定的元素的属性,都存到这个对象中。

通过 ECMAScript的属性操作都是存在内存中,而通过DOM属性操作,属性及值存在DOM文档中

使用ECMAScript的属性操作 . 和 [] 获取或设置w3c规定之外的非合法属性,会返回undefined。

  • - el.attributes 元素所有属性名的集合(不包括属性值)
  • - el.getAttribute("attr") 获取属性
  • - el.setAttribute("attr","val") 设置属性
  • - el.removeAttribute("attr") 移出属性
  • - el.hasAttribute("attr") 判断是否有这个属性
  • - 只要操作了innerHTML 元素的所有子元素上,存在内存中的事件和相关的属性都会丢失。如果希望元素的某些属性在操作了父级的innerHTML 之后,还存在就把这个属性加在 DOM 中

3.1 . 和 [] 都是 ECMAScript的属性操作:

<body>
    <div id="box" class="box" kkb="DOM"></div>
<script>
{
    //. 和 [] 都是 ECMAScript的属性操作,通过 ECMAScript的属性操作都是存在内存中,而通过DOM属性操作,属性及值存在DOM文档中

    //直接通过. 和 [] 获取到的是存在内存中的属性及值
    let box = document.querySelector("div");
    console.log(box.id);//box
    console.log(box.className);//获取class的值时,为避免冲突,必须使用className

    //使用ECMAScript的属性操作 . 和 [] 获取或设置w3c规定之外的非合法属性,会返回undefined
    console.log(box.kkb);//undefined

}    
</script>
</body>

3.2 DOM的属性操作:

  • - el.attributes 元素所有属性名的集合(不包括属性值)
  • - el.getAttribute("attr") 获取属性。attr必须和文档中属性名一致,获取不到就返回null
  • - el.setAttribute("attr","val") 设置属性
  • - el.removeAttribute("attr") 移出属性
  • - el.hasAttribute("attr") 判断是否有这个属性。返回布尔值
  • - 只要操作了innerHTML 元素的所有子元素上,存在内存中的事件和相关的属性都会丢失。如果希望元素的某些属性在操作了父级的innerHTML 之后,还存在就把这个属性加在 DOM 中
<body>
    <div id="box" class="box" kkb="DOM"></div>
<script>
{
    /*
    - el.attributes 元素所有属性名的集合(不包括属性值)
    - el.getAttribute("attr") 获取属性
    - el.setAttribute("attr","val") 设置属性
    - el.removeAttribute("attr") 移出属性
    - el.hasAttribute("attr") 判断是否有这个属性
    */
    let box = document.querySelector("div");
    //el.attributes元素所有属性的集合
    console.log(box.attributes);//NamedNodeMap {0: id, 1: class, 2: kkb, id: id, class: class, kkb: kkb, length: 3}

    //el.getAttribute("attr") 获取属性
    console.log(box.getAttribute("class"));//box
    //也可以获取非w3c的属性
    console.log(box.getAttribute("kkb"));//DOM

    //el.setAttribute("attr","val") 设置属性
    box.setAttribute("miaov","kaikeba");
    console.log(box.attributes);//NamedNodeMap {0: id, 1: class, 2: kkb, 3: miaov, id: id, class: class, kkb: kkb, miaov: miaov, length: 4}
    
    // el.removeAttribute("attr") 移出属性
    box.removeAttribute("kkb");
    console.log(box.attributes);//NamedNodeMap {0: id, 1: class, 2: miaov, id: id, class: class, miaov: miaov, length: 3}

    //el.hasAttribute("attr") 判断是否有这个属性 返回布尔值
    console.log(box.hasAttribute("kkb"));//false

}    
</script>
</body>

3.3 DOM属性操作和ECMAScript属性操作区别:

  1. ECMAScript属性操作,操作的是元素获取后编译成的对象,具体的数据存在内存中;DOM属性操作,值是存在文档中。
  2. ECMAScript属性操作,内存中可以存任何类型的数据;DOM中只能存字符串类型的数据,不是字符串也会转成字符串
  3. 通过ECMAScript属性操作设置的属性,再通过DOM属性操作获取时,会返回null(因为通过ECMAScript属性操作设置的属性是存在内存中的,在DOM文档里面获取不到)
  4. 通过DOM属性操作设置的非法属性,再通过ECMAScript属性操作获取时,会返回undefined(因为通过DOM属性设置的值并没有保存在内存中)
  5. 只要操作了innerHTML 元素的所有子元素上,存在内存中的事件和相关的属性都会丢失。如果希望元素的某些属性在操作了父级的innerHTML 之后,还存在就把这个属性加在 DOM 中

<body>
    <div id="box" class="box">
        <div></div>
    </div>
<script>
{
    let box = document.querySelector("#box");

    //ECMAScript属性操作,操作的是元素获取后编译成的对象,具体的数据存在内存中。内存中可以存任何类型的数据
    box.index = 0;

    //DOM属性操作,值是存在文档中。DOM中只能存字符串类型的数据,不是字符串也会转成字符串
    box.setAttribute("kkb","kaikeba");
    box.setAttribute("miao",1);
    console.log(typeof box.getAttribute("miao"));//string

    //通过ECMAScript属性操作设置的属性,再通过DOM属性操作获取时,会返回null(因为通过ECMAScript属性操作设置的属性是存在内存中的,在DOM文档里面获取不到)
    console.log(box.getAttribute("index"));//null

     //通过DOM属性操作设置的非法属性,再通过ECMAScript属性操作获取时,会返回undefined(因为通过DOM属性设置的值并没有保存在内存中)
    console.log(box.kkb);//undefined

    //只要操作了innerHTML 元素的所有子元素上,存在内存中的事件和相关的属性都会丢失。如果希望元素的某些属性在操作了父级的innerHTML 之后,还存在就把这个属性加在 DOM 中
    let childBox = box.children[0];
    childBox.index = 1;
    childBox.setAttribute("kkb","kaikeba");
    //注意此处是操作父级的innerHTML 之后才会有问题
    box.innerHTML = box.innerHTML;
    console.log(box.children[0].index);//undefined
    console.log(box.children[0].getAttribute("kkb"));//kaikeba
    
}    
</script>
</body>

4.data 自定义属性

- 在标签中定义data自定义属性:data-key="value";

-data自定义属性本身是将属性存在DOM文档中,所以只能是字符串类型,不是也会转为字符串类型

- 在js操作该元素的 data 自定义属性:el.dataset

  1. - 获取:el.dataset.key
  2. - 设置: el.dataset.key = "value"
<body>
    <div id="box" class="box" data-kkb="kaikeba">
        <div></div>
    </div>
<script>
{
    let box = document.querySelector("#box");
    console.log(box.dataset.kkb);//kaikeba
    box.dataset.kkb = "miaov";
    console.log(box.dataset.kkb);//miaov

}    
</script>
</body>

5.节点操作

5.1创建节点

  • 语法:element document.createElement("tagName"); 创建一个节点
  • 参数:tagName 标签名称
  • 返回值:创建好的节点

createElement()可以创建任何类型的标签,甚至可以是w3c中没有的,但是建议每次都创建合法标签。

注意:element document.createElement("tagName");方法创建好节点后不会直接渲染到页面,还需要调用添加节点方法,才能真正渲染到页面。

<body>
    <div id="box">
    </div>
<script>
{
    //elment document.createElement("tagName");创建元素
    let box = document.querySelector("#box");
    let h1 = document.createElement("h1");
    h1.innerHTML = "标题";
    console.log(h1);//<h1>标题</h1>
}    
</script>
</body>

5.2向页面中添加节点

- el.appendChild(node) 在元素的末尾添加一个子级

- el.insertBefore(newNode,oldNode) 在 oldNode 前边添加入 newNode。第二个参数oldNode是必须的,如果第一个参数不存在,等同于appendChild()操作会在末尾添加一个子级

- 在使用 appendChild 和 insertBefore时,如果添加是一个页面上已经存在的节点,会先从原位置删除,然后在添加到新的位置去。

<body>
    <div id="box">
        <p>这是一个p标签</p>
    </div>
<script>
{
    let box = document.querySelector("#box");
    let p = document.querySelector("p");

    let h1 = document.createElement("h1");
    h1.innerHTML = "标题";
    // box.appendChild(h1);   //在末尾添加元素 
    box.insertBefore(h1,p); //在某节点之前添加一个节点
}    
</script>
</body>

结果: 

添加已有节点时:如果添加是一个页面上已经存在的节点,会先从原位置删除,然后在添加到新的位置去。

<body>
    <div id="box">
        <div id="div1"></div>
    </div>
    <div id="box2"></div>
<script>
{
    let box = document.querySelector("#box");
    let div1 = box.querySelector("#div1");
    let box2 = document.querySelector("#box2");
    box2.appendChild(div1);
}    
</script>
</body>

使用insertBefore(newNode,oldNode) :

<body>
    <div id="box">
        <div id="div1"></div>
    </div>
    <div id="box2">
        <h1></h1>
    </div>
<script>
{
    let box = document.querySelector("#box");
    let div1 = box.querySelector("#div1");
    let box2 = document.querySelector("#box2");
    let h1 = document.querySelector("h1");
    // box2.appendChild(div1);
    box2.insertBefore(div1,h1);
}    
</script>
</body>

 

5.3 替换节点

- parent.replaceChild(newNode,oldNode) 将oldNode替换成newNode。两个节点需在同一个parent下

使用已存在的节点进行替换,会先从原位置删除,然后在添加到新的位置去。

<body>
    <div id="box">
        <div id="div1"></div>
    </div>
<script>
{
    let box = document.querySelector("#box");
    let div1 = box.querySelector("#div1");
    let h1 = document.createElement("h1");
    box.replaceChild(h1,div1);
}    
</script>
</body>

 

5.4删除节点

- parent.removeChild(el) 删除掉某个子元素。返回值为删除的节点。建议使用

-parent.remove()删除子元素。新方法兼容性不是很好。返回值undefined

<body>
    <div id="box">
        <div id="div1"></div>
        <h1>标题</h1>
    </div>
<script>
{
    let box = document.querySelector("#box");
    let div1 = box.querySelector("#div1");
    let h1 = box.querySelector("h1");
    console.log(box.remove(h1));
    console.log(box.removeChild(div1));
}    
</script>
</body>

 

5.5克隆节点

- node.cloneNode(deep)

  1. - deep: 默认为false
  2. - deep 为 true, 克隆元素及属性,以及元素的内容和后代
  3. - deep 为 false, 只克隆元素本身,及它的属性

克隆节点,只会克隆元素内容,不会克隆元素上的事件。

    <style>
        #box {
            width: 100px;
            height: 100px;
            border: 1px solid red;
        }
    </style>
</head>
<body>
    <div id="box">
        <div id="div1"></div>
        <h1>标题</h1>
    </div>
<script>
{
    let box = document.querySelector("#box");
    let box2 = box.cloneNode();
    console.log(box2);//<div id="box"></div>
    let box3 = box.cloneNode(true);
    console.log(box3);//<div id="box"><div id="div1"></div><h1>标题</h1></div>
    
    box.appendChild(box3);

}    
</script>
</body>

6.文档碎片document.createDocumentFragment()

使用循环添加innerHTML时不建议直接添加,而是将所有元素累加到字符串中,最后循环完后再一次性添加:

6.1使用字符串累加:

直接添加1000个div时,用时:1311.780029296875ms

    <style>
        #box div{
            width: 100px;
            height: 100px;
            border: 1px solid black;
            background: red;
            float: left;
            margin: 10px;
        }
    </style>
</head>
<body>
    <div id="box"></div>
<script>
{
    let box = document.querySelector("#box");

    //使用循环添加innerHTML时不建议直接添加,而是将所有元素累加到字符串中,最后循环完后再一次性添加
    // let inner = '';
    console.time();
    
    for (let i = 0; i < 1000; i++) {
        box.innerHTML += '<div id="box">'+i+'</div>';
    }
    console.timeEnd();//发现总用时:default: 1311.780029296875ms

}    
</script>
</body>

使用先存进字符串,再一次性添加时:default: 9.087890625ms,性能大大提高

    console.time();
    let inner = '';
    
    for (let i = 0; i < 1000; i++) {
        inner += '<div id="box">'+i+'</div>';
    }
    box.innerHTML = inner;
    console.timeEnd();//发现总用时:default: 9.087890625ms

 6.2使用文档碎片document.createDocumentFragment()

普通创建:

    //直接添加节点
    console.time();
    for (let i = 0; i < 1000; i++) {
        let div = document.createElement("div");
        div.innerHTML = i;
        box.appendChild(div);
    }
    console.timeEnd();//发现总用时:default: 15.39208984375ms

使用文档碎片: 

    console.time();
    let fragment = document.createDocumentFragment();
    for (let i = 0; i < 1000; i++) {
        let div = document.createElement("div");
        div.innerHTML = i;
        fragment.appendChild(div);
    }
    box.appendChild(fragment);
    console.timeEnd();//发现总用时:default: 8.47119140625ms

7.元素的尺寸获取

7.1offset

  • - offsetWidth 可视宽度
  • - offsetHeight 可视高度
  • - offsetLeft 距离定位父级的left坐标
  • - offsetTop 距离定位父级的top坐标

元素offsetWidth/offsetHeight可视宽高 = 元素width/height + border + padding

元素offsetTop/offsetLeft:元素距离定位父级的top/left位置 = 元素top/left + margin

    <style>
        #box {
            position: relative;
            width: 400px;
            height: 400px;
            margin: 100px 0 0 700px;
            border: 1px solid black;
        }
        #box div{
            position: absolute;
            top: 50px;
            left: 50px;
            width: 100px;
            height: 100px;
            border: 4px solid black;
            padding: 40px;
            background: red;
            margin: 10px;
        }
    </style>
</head>
<body>
    <div id="box">
        <div></div>
    </div>
<script>
{
    let box = document.querySelector("#box");
    let div = box.querySelector("div");
    //元素offsetWidth/offsetHeight可视宽高 = 元素width/height + border + padding
    console.log(div.offsetWidth,div.offsetHeight);//188 188

    //元素offsetTop/offsetLeft:元素距离定位父级左上角的位置 = 元素top/left + margin
    console.log(div.offsetTop,div.offsetLeft);//60 60
}    
</script>
</body>

7.2client

  • - clientWidth = 可视宽度 - border
  • - clientHeight = 可视高度 - border
  • - clientTop 上边框宽度
  • - clientLeft 左边框宽度
    <style>
        #box {
            position: relative;
            width: 400px;
            height: 400px;
            margin: 100px 0 0 700px;
            border: 1px solid black;
        }
        #box div{
            position: absolute;
            top: 50px;
            left: 50px;
            width: 100px;
            height: 100px;
            border: 4px solid black;
            padding: 40px;
            background: red;
            margin: 10px;
        }
    </style>
</head>
<body>
    <div id="box">
        <div></div>
    </div>
<script>
{
    /*
    - clientWidth = 可视宽度 - border
    - clientHeight = 可视高度 - border
    - clientTop 上边框宽度
    - clientLeft 左边框宽度
    */
    let box = document.querySelector("#box");
    let div = box.querySelector("div");
    //元素clientWidth/clientHeight = 元素width/height+ padding
    console.log(div.clientWidth,div.clientHeight);//180 180

    //元素clientTop/clientLeft:元素上边框宽度/元素左边框宽度
    console.log(div.clientTop,div.clientLeft);//4 4
}    
</script>
</body>
</html>

7.3scroll

  • - scrollWidth 内容宽度
  • - scrollHeight 内容高度
  • - scrollLeft 左右滚动距离
  • - scrollTop 上下滚动距离
  1. scrollHeight:如果内容高度 > 元素高度,scrollHeight就为内容高度,否则scrollHeight就为元素高度;有滚动条会去除滚动条高度
  2. scrollWidth:如果内容宽度 > 元素宽度,scrollWidth就为内容宽度,否则scrollWidth就为元素宽度;有滚动条会去除滚动条宽度
  3. 元素scrollTop/scrollLeft:上下滚动条位置/左右滚动条位置
    <style>
        #box {
            position: relative;
            width: 400px;
            height: 400px;
            margin: 100px 0 0 700px;
            border: 1px solid black;
            overflow: auto;
        }
        #box div{
            position: absolute;
            top: 50px;
            left: 50px;
            width: 100px;
            height: 100px;
            border: 4px solid black;
            padding: 40px;
            background: red;
            margin: 10px;
        }
    </style>
</head>
<body>
    <div id="box">
        <div>这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容这是div内容</div>
    </div>
<script>
{
    /*
    - scrollWidth 内容宽度
    - scrollHeight 内容高度
    - scrollLeft 左右滚动距离
    - scrollTop 上下滚动距离
    */
    let box = document.querySelector("#box");
    let div = box.querySelector("div");
    //scrollHeight:如果内容高度 > 元素高度,scrollHeight就为内容高度,否则scrollHeight就为元素高度;有滚动条会去除滚动条高度
    console.log(box.scrollHeight);//3359

    //scrollWidth:如果内容宽度 > 元素宽度,scrollWidth就为内容宽度,否则scrollWidth就为元素宽度;有滚动条会去除滚动条宽度
    console.log(box.scrollWidth);//400  有滚动条383
    

    //元素scrollTop/scrollLeft:上下滚动条位置/左右滚动条位置
    box.onscroll = () =>{
        console.log(box.scrollTop,box.scrollLeft);//110 0 在滚动条滚动时不断变化
    }
}    
</script>
</body>

7.4 getBoundingClientRect()

  • - left 元素左侧距离可视区左侧距离  
  • - right 元素右侧距离可视区左侧距离
  • - top 元素顶部距离可视区顶部距离
  • - bottom 元素底部距离可视区顶部距离
  • - width 元素的可视宽度
  • - height 元素的可视高度

getBoundingClientRect()随着元素在页面上的移动,各个位置会发生改变。此方法本身不兼容IE浏览器低版本

    <style>
        div{
            height: 100px;
            border: 1px solid black;
            padding: 40px;
            margin: 10px;
        }

        #box {
            position: relative;
            top: 20px;
            left: 40px;
            height: 200px;
            border: 4px solid black;
            background: red;
        }
    </style>
</head>
<body>
    <div></div>
    <div></div>
    <div></div>
    <div id="box"></div>
    <div></div>
    <div></div>
<script>
{
    /*
        getBoundingClientRect()
            - left 元素左侧距离可视区左侧距离     margin+left+父级距离左侧位置 即 距离浏览器左侧的可视距离
            - right 元素右侧距离可视区左侧距离
            - top 元素顶部距离可视区顶部距离
            - bottom 元素底部距离可视区顶部距离
            - width 元素的可视宽度
            - height 元素的可视高度
    */

    let box = document.querySelector("#box");
    box.onclick = () =>{
        console.log(box.getBoundingClientRect().left,box.getBoundingClientRect().right,box.getBoundingClientRect().top,box.getBoundingClientRect().bottom,box.getBoundingClientRect().width,box.getBoundingClientRect().height);
    }
}    
</script>
</body>

getBoundingClientRect()不兼容IE浏览器低版本,如果需要兼容可以使用offset不断获取其父级的相对位置+自身和父级的边框宽度:

    <style>
        body {
            margin: 0;
        }
        div{
            position: relative;
            top: 100px;
            left: 100px;
            width: 400px;
            height: 400px;
            border: 1px solid black;
            padding: 40px;
        }

        #box {
            position: absolute;
            top: 20px;
            left: 40px;
            width: 100px;
            height: 100px;
            border: 4px solid black;
            background: red;
        }
    </style>
</head>
<body>
    <div>
        <div id="box"></div>
    </div>
<script>
{
    let box = document.querySelector("#box");

    let getPageOffset = (el) =>{
        let top = el.offsetTop + el.clientTop;
        let left = el.offsetLeft + el.clientLeft;

        while(el.offsetParent){
            el = el.offsetParent;
            top += el.offsetTop + el.clientTop;
            left += el.offsetLeft + el.clientLeft;
        }
        return {top,left}
    }

    console.log(getPageOffset(box));//{top: 125, left: 145}  本身top20+父级top100 + 上边框   本身left40+父级left100+左边框
    
}    
</script>
</body>

 

 

8 表格相关操作

- tBodies、tHead、tFoot、rows、cells

  • tBodies获取HTMLCollection 获取到的是一组tBody
  • tHead获取表头tHead
  • rows 获取所有行(tr)
  • cells 获取所有列
  • tFoot 获取tFoot
<body>
<table id="table" border="1px" width="200px">
    <thead>
        <tr>
            <th>表头1</th>
            <th>表头2</th>
            <th>表头3</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
    </tbody>
    <tbody>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <td></td>
            <td></td>
            <td></td>
        </tr>
    </tfoot>
</table>
<script>
{
    let table = document.querySelector("#table");
    
    console.log(table.tHead);
    console.log(table.tBodies);
    console.log(table.tBodies[0].rows);
    console.log(table.tBodies[0].rows[0].cells);
    console.log(table.tFoot);
}    
</script>
</body>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值