zoukankan      html  css  js  c++  java
  • JS中的动态合集与静态合集

    JS的动态合集

    前言

    DOM是JavaScript重要组成部分,在DOM中有三个特别的集合分别是NodeList(节点的集合),NamedNodeMap(元素属性的集合)和HTMLCollection(html元素的集合)。这三个集合有一些共同的特点:它们都是一个类数组对象,可以通过中括号表达式来访问集合中元素,也有length属性。但它们并不是数组,而且它们都是动态的(querySelectorAll()返回的NodeList除外),会根据页面元素的变化而变化。下面就来介绍一下它们。

    NodeList集合

    如何获取NodeList集合

    DOM将HTML页面解析成一个由多层次节点构成的结构。节点是页面结构的基础,而所有节点继承自Node类型,因此所有节点共享着基本的属性和方法。Node类型有一个childNodes属性,所以所有节点都拥有这个属性。而通过这个属性就可以得到一个保存着本节点的子节点组成的NodeList对象。

    如何操作NodeList

    NodeList可以通过方括号表达式来访问,也可以通过item()方法来访问,也有length属性,可以访问元素个数。 虽然javascript中的数组可以修改length属性。但NodeList集合并不是数组,而且它是页面一片区域的DOM结构映射。所以请不要修改NodeList对象的length值。

    var firstChild = someNode.childNodes[0];//获取第一个元素
    var secondChild = someNode.childNodes.item(1);//获取第二个元素
    var count = someNode.childNodes.length;//获取集合长度

    NamedNodeMap

    如何获取NamedNodeMap

    Element类型这种DOM节点是唯一拥有attributes属性的一种节点类型。而attribute属性中就包含NamedNodeMap集合。它由元素的特性组成。所以只要是元素节点,调用attributes属性就可以得到NamedNodeMap集合。

    如何操作NamedNodeMap集合

    可能一些人没有听过NamedNodeMap对象,该对象的常见实例对象是attributes属性

    <div id="test"></div>
    <script>
        var attrs = test.attributes;
        console.log(attrs instanceof NamedNodeMap); //true
    </script>
    

    NamedNodeMap集合的元素拥有nodeName和nodeValue属性,分别表示元素特性名称和特性值,也拥有以下方法:

    • getNamedItem(name);返回nodeName属性等于name的节点;
    • removeNamedItem(name);从列表中移除nodeName节点;
    • setNamedItem(node);向列表中添加节点,以节点nodeName为属性索引;
    • item(pos);返回位于数字pos位置的节点。
    var className = element.attributes.getNamedItem('class').nodeValue;
    var className1 = element.attributes['class'].nodeValue;
    var oldAttr = element.attributes.removeNamedItem('class');
    

    一般元素节点的getAttribute()、removeAttribute()和setAttribute()方法都可以完成以上操作

    HTMLCollection

    如何得到HTMLCollection集合

    HTMLCollection是元素节点的集合可以通过getElementsByTagName()方法(获取同类型的元素)、getElementsByClassName()(获取class特性相同的元素)、getElementsByName()方法(获取name特性相同的元素)、document的anchors属性(包含name特性的a元素),forms属性(包含文档所有form元素),images属性(包含文档所有img元素),links属性(文档所有带href特性的a元素)。

    与NodeList区别

    NodeList集合主要是Node节点的集合,而HTMLCollection集合主要是Element元素节点的集合。Node节点共有12种,Element元素节点只是其中一种。

    注意事项

    这三个集合都是“动态的”;当文档结构发生变化时,它们都会更新,所以以下操作就会发生错误:

    var divs = document.getElementsByTagName('div');
    for (var i = 0; i < divs.length; i++) {
        var div = document.createElement('div');
        document.body.appendChild(div);
    }

    以上代码中的for循环将会一直执行,因为div得到的HTMLCollection集合是动态的,当每次给body添加元素divs都会进行更新,所以会一直循环下去。

    解决方法1:将初始的集合的length存起来

    var divs = document.getElementsByTagName('div');
    for (var i = 0, var len = divs.length; i < len; i++) {
        var div = document.createElement('div');
        document.body.appendChild(div);
    }

    解决方法2:将以上集合转化为数组

    var divs = document.getElementsByTagName('div');
    //将HTMLCollection转换为数组(此方法在IE8及以前不能用)
    var divsArr = Array.prototype.slice.call(divs,0);
    for (var i = 0; i < divsArr.length; i++) {
        var div = document.createElement('div');
        document.body.appendChild(div);
    }

    由于IE8-浏览器将NodeList实现为一个COM对象,不能使用Array.prototype.slice()方法,必须手动枚举所有成员

    将以上集合转为数组的方法(通用):

    function convertListToArray(nodes) {
       var array = null;
       try{//标准浏览器
           array = Array.prototype.slice.call(nodes,0);
       }catch(ex){//IE8及以下遍历每一项分别添加到数组中
           array = new Array();
           for(var i = 0,len = nodes.length;i < len;i++){
               array.push(nodes[i]);
           }
       }
       return array;
    }

    JS的静态合集

    前言

    除了getElementsByClassName()方法外,HTML5中DOM拓展了querySelectorAll()、querySelector()和matchesSelector()这3种方法,通过CSS选择符查询DOM文档取得元素的引用的功能变成了原生的API,解析和树查询操作在浏览器内部通过编译后的代码来完成,极大地改善了性能。

    与getElementById()方法不同,querySelector()方法得到的对象是静态对象

    与getElementsByTagName()等方法不同,querySelectorAll()方法得到的类数组对象是静态合集。

    querySelector()

    querySelector()方法接收一个CSS选择符,返回与该模式匹配的第一个元素,如果没有找到匹配的元素,返回null。该方法既可用于文档document类型,也可用于元素element类型。

    <body style="height: 100%;">
    <div class="box" id="box" style="height: 200px;">
    <ul class="list" style="height:100px">
            <li class="in" style="height: 30px;">1</li>
            <li class="in" style="height: 30px;" title="test">2</li>
            <li class="in" style="height: 30px;">3</li>
        </ul>    
    </div>
    <script>
        //因为没有.null类名,所以返回null
        var oNull = document.querySelector('.null');
        console.log(oNull); //null
        //通过<body>标签取得元素
        var body = document.querySelector("body");
        console.log(body.style.height); //100%
        //通过id属性取得元素
        var oBox = document.querySelector('#box');
        console.log(oBox.style.height); //200px
        //通过结合元素的类选择器取得元素
        var oList = document.querySelector('ul.list');
        console.log(oList.style.height); //100px
        //通过类名取得元素
        var oIn = document.querySelector('.in');
        console.log(oIn.innerHTML); //1
        //通过属性选择器取得元素
        var oTest = body.querySelector('[title="test"]');
        console.log(oTest.innerHTML); //2
    </script>
    </body> 
    

    querySelectorAll()

    querySelectorAll()接收一个CSS选择符,返回一个类数组对象NodeList的实例。具体来说,返回的值实际上是带有所有属性和方法的NodeList,而其底层实现则类似于一组元素的快照,而非不断对文档进行搜索的动态查询。这样实现可以避免使用NodeList对象通常会引起的大多数性能问题。

    没有匹配元素时,返回空的类数组对象,而不是null

    <body style="height: 100%;">
    <div class="box" id="box" style="height: 200px;">
    <ul class="list" style="height:100px">
            <li class="in" style="height: 30px;">1</li>
            <li class="in" style="height: 30px;" title="test">2</li>
            <li class="in" style="height: 30px;">3</li>
        </ul>    
    </div>
    <script>
        //返回[]
        var oNull = document.querySelectorAll('.null');
        console.log(oNull);
        //取得body元素
        var body = document.querySelectorAll("body")[0];
        console.log(body.style.height); //100%
        //取得所有class为"in"的元素
        var oIn = document.querySelectorAll('.in');
        for (var i = 0; i < oIn.length; i++) {
            console.log(oIn[i].innerHTML); //1,2,3    
        }
        //取得title属性为test的元素
        var oTest = body.querySelectorAll('[title="test"]');
        console.log(oTest); //[li.in]
    </script>
    </body>
    

    缺陷

    selector类方法在元素上调用时,指定的选择器仍然在整个文档中进行匹配,然后过滤出结果集,以便它只包含指定元素的后代元素。它意味着选择器字符串能包含元素的祖先而不仅仅是所匹配的元素

    <div id="container">
        <div>1</div>
        <div>2</div>
    </div>
    <script>
        var container = document.getElementById('container');
        console.log(container.querySelectorAll('div div')); //[div div]
    </script>

    所以,如果出现后代选择器,为了防止该问题,可以在参数中显式地添加当前元素的选择器

    <div id="container">
        <div>1</div>
        <div>2</div>
    </div>
    <script>
        var container = document.getElementById('container');
        console.log(container.querySelectorAll('#container div div')); //[]
        console.log(container.querySelectorAll('#container div')); //[div div]
        console.log(container.querySelectorAll('div')); //[div div]
    </script>
  • 相关阅读:
    react ts axios 配置跨域
    npm run eject“Remove untracked files, stash or commit any changes, and try again.”错误
    java 进程的参数和list的线程安全
    帆软报表 大屏列表跑马灯效果JS
    帆软报表 快速复用数据集,避免重复劳动
    分析云 OA中部门分级思路和实现方法
    分析云 分段器 只显示一个块的数据
    分析云 更改服务默认的端口号
    分析云U8项目配置方法新版本(2)
    Oracle 创建时间维度表并更新是否工作日字段
  • 原文地址:https://www.cnblogs.com/MasterYao/p/8743133.html
Copyright © 2011-2022 走看看