【问题标题】:Cannot edit classList while looping through it循环时无法编辑classList
【发布时间】:2017-03-27 21:12:44
【问题描述】:

我有一个这样的元素:

<span class="util bg-color-yellow tooltip bg-color-red"></span>

我想删除所有以“bg-color-”开头的类,所以我只需循环遍历所有类,然后删除匹配的类:

var element = document.getElement......;

var elementClasses = element.classList;


for( var i = 0, l = elementClasses.length; i < l; i++ )
{
    var className = elementClasses[i];

    // console.log(i);
    // console.log(name);

    if( className.startsWith('bg-color-') )
    {
        element.classList.remove(className);
    }

    console.log('elementClasses contain :');
    console.log(elementClasses);
}

当它匹配 'bg-color-' 类时,它成功删除了类名,但它也会编辑变量 elementClasses,就好像它是对 element.classList 的引用一样,即使它是一个变量(副本)它。

第一个循环:

elementClasses = [ util bg-color-yellow tooltip bg-color-red ]

第二个循环:

elementClasses = [ util bg-color-yellow tooltip bg-color-red ]

第三次循环:

elementClasses = [ util tooltip bg-color-red ]

问题出现了elementClasses 的修改时间与 elemnt.classList 的修改时间相同!

  • 这怎么可能?
  • 实际上elementClasseselement.classList 的一种引用吗?
  • elementClasses 是否在每次修改 element.classList 时都自行重新创建?

.

非常感谢! :)

【问题讨论】:

  • 所以向后循环
  • 不要使用for (/*...*/) {/*...*/}循环,而是使用[...elementClasses].forEach(/*...*/)]

标签: javascript loops dom


【解决方案1】:

很高兴您已经确定了导致问​​题的原因。现在寻求解决方案:

// ES6
[...elementClasses].forEach((className, i) => {
// OR ES5
Array.prototype.slice.call(elementClasses).forEach(function (className, i) {

    // console.log(i);
    // console.log(className);

    if( className.startsWith('bg-color-') )
    {
        element.classList.remove(className);
    }

    console.log('elementClasses contain :');
    console.log(elementClasses);
});

使用这两种方法中的任何一种,classList 都会被浅拷贝,以确保在修改数组时不会跳过条目。

为了回答您的另一个问题,您原始代码中的elementClasses 确实是对element.classList 的引用,这就是为什么它们都被修改了而其中一个被修改的原因。

在我的 ES6 建议中,[...elementClasses] 使用扩展运算符将浅拷贝复制到原生 Array,而 ES5 方法在原始 element.classList 上调用 slice() 来制作它的浅拷贝。

现在进行演示:

var element = document.querySelector('span');
var elementClasses = element.classList;

// ES6
// [...elementClasses].forEach((className, i) => {
// OR ES5
Array.prototype.slice.call(elementClasses).forEach(function (className, i) {

    console.log(i);
    console.log(className);

    if( className.startsWith('bg-color-') )
    {
        element.classList.remove(className);
    }

    console.log('elementClasses contain :');
    console.log(JSON.stringify(elementClasses));
});
&lt;span class="util bg-color-yellow tooltip bg-color-red"&gt;&lt;/span&gt;

【讨论】:

  • 感谢您的提示!
【解决方案2】:

请看这篇文章,这解释了当你使用'='符号时javascript如何复制变量的答案

Copy a variable's value into another

【讨论】:

  • 哇,谢谢我以前从未听说过 javascript 参考。这对未来肯定会很有帮助!
【解决方案3】:

在您的实现中,elementClass 实际上并不是element.classList 的副本。它是对同一对象的引用。要复制对象,请考虑使用.slice()

看到这个问题: Copying array by value in JavaScript

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多