DOM操作的一个小坑

最近在苦读《JavaScript高级程序教程》,真不愧是前端圣经,学到了很多东西。

nodeList、NameNodeMap、HTMLCollection这三个集合是动态的!每当文档发生变化,它们都会得到更新。因此,它们始终保存着最新、最准确的信息。

在DOM这段遇到一个有意思的例子:

例子1: 增加内容

这个例子首先获取div,然后在一个for循环中,往body追加新的div元素。结果会一直追加。

第一个行代码会获取文档中所有<div>元素的HTMLCollection。这个集合是动态的。所以,只要有新的<div>元素被添加到页面中,这个元素也同时添加到

HTMLCollection中。而for循环每次都要对这个集合进行重新求值。所以就会出现这个有趣的例子。

<body>
    <div></div>
    <script>
        // 获取div
        let myDiv = document.getElementsByTagName('div');
        for (let i = 0; i < myDiv.length; i++) {
            console.log(myDiv);
            let div = document.createElement('div');
            document.body.appendChild(div);
            // 为防止陷入死循环,这里设置一下
            if (myDiv.length === 10) {
                break;
            }
        }
    </script>
</body>

改进1、

将length赋予一个变量。

<body>
    <div></div>
    <script>
        // 获取div
        let myDiv = document.getElementsByTagName('div');
        // 改进
        for (let i = 0,len = myDiv.length; i < len; i++) {
            console.log(myDiv);
            let div = document.createElement('div');
            document.body.appendChild(div);
            // 为防止陷入死循环,这里设置一下
            if (myDiv.length === 10) {
                break;
            }
        }
    </script>
</body>

改进2、

使用 querySelectorAll('div') 代替 getElementByTagName('div')  

querySelectorAll()方法是DOM扩展里的方法,这个方法返回的是一个Nodelist实例,但是,返回的值实际上是带有所有属性和方法的NodeList,而底层实现类似于一组元素的快照,而非不断对文档进行搜索的动态查询,所以可以避免使用Nodelist对象通常引起的问题。

< body >
< div ></ div >
< script >
// 获取div
// 改进
let myDiv = document . querySelectorAll ( ' div ' );
for ( let i = 0 ; i < myDiv . length ; i ++ ) {
console . log (myDiv );
let div = document . createElement ( ' div ' );
document . body . appendChild (div );
// 为防止陷入死循环,这里设置一下
if (myDiv . length === 10 ) {
break ;
}
}
< / script >
</ body >

这两个返回结果都是一样的。

说完了增加,在看一下减少的问题

例二、

需求:现在我想把同时有 username 和 current 两个类名的标签,去掉其中的current类名。

按理说最后应该要输出三个div 每个div标签有一个类名 username

<body>
    <div class="username current"></div>
    <div class="username current"></div>
    <div class="username current"></div>
    <script>
        // 获取
        let userNames = document.getElementsByClassName('username current');
        // 注意这里,把len赋予一个变量
        for(let i = 0,len = userNames.length; i < len; i++){
            userNames[i].classList.remove('current');
        }
    </script>
</body>

事实上是这样子的

以及这样子的

这是因为,把userNames的长度赋予一个变量导致的问题。len = 3;然后再for循环中,

第二次for循环的时候,i 的值为1,但是这时的userNames的数组长度是2。

因为第一次循环的时候已经把第一个div元素的current类去除了。

所以第二次循环时,remove的是最后一个div的类。

当第三次时,i为2, userNames的长度为1.。 所以这时取得的值为undefined,而undefined是基本数据类型,不能转为对象,理应没有方法。也就导致了语法错误。

改进1、

    <script>
        // 获取
        let userNames = document.getElementByClassName('username current');
        // 改进
        for(let i = 0;i < userNames.length;  i++){
            userNames[i].classList.remove('current');
        }
    </script>

改进2、

    <script>
        // 获取
        // 改进
        let userNames = document.querySelectorAll('.username.current');
        // 注意这里,把len赋予一个变量
        for(let i = 0,len = userNames.length; i < len; i++){
            userNames[i].classList.remove('current');
        }
    </script>

猜你喜欢

转载自www.cnblogs.com/chinabin1993/p/9402561.html
今日推荐