开发者问题收集

为什么 classList 会返回错误:Uncaught TypeError: Cannot read properties of undefined (reading 'classList')?

2022-06-18
966

我不明白为什么会出现错误: 未捕获的类型错误:无法读取未定义的属性(读取“classList”) console.log(slid[numberArray].classList)- 可以工作,但是 slid[numberArray].classList.add('active') - 无法工作 我知道这不是一个好的代码,但我仍在学习,我想自己制作一个滑块

const slid = [...document.querySelectorAll('.slid')];
const arrows = document.querySelectorAll('.arrows-slider .arrow');

slid.forEach(s => {
    if( s.classList.contains('active') == false){
         s.style.opacity = '0';
    }
 });

arrows.forEach( arrow =>{
    arrow.addEventListener('click', function(){
        if(this.classList.contains('arrows-right')){
            slid.forEach(s => {
                if( s.classList.contains('active')){
                    s.classList.remove('active');
                    let numberArray = slid.indexOf(s);
                    numberArray ++;
                    slid[numberArray].classList.add('active');
                    console.log(slid[numberArray].classList);
                }
             });
        }else if( this.classList.contains('arrows-left')){

        }

    });
});
.slider {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    background-image: url('../img/mirrored_squares.png');
    height: 100vh;
}

.slid {
    position: absolute;
    width: 100%;
    height: 100vh;
    opacity: 0;
}

.active {
    opacity: 1 !important;
}

.img-slid {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 35%;
    height: 50%;
    background-size: cover;
}

.engine {
    background-image: url("../img/silnik.jpg");
}

.exhaust {
    background-image: url("../img/wydech.jpg");
}



.slid-text {
    position: absolute;
    top: 50%;
    left: 11%;
    transform: translateY(-50%);
    font-size: 8rem;
    text-transform: uppercase;
    color: #fff;
    font-family: 'Black Ops One', cursive;

}

.number-slaid {
    position: absolute;
    bottom: 8%;
    right: 8%;
    font-size: 2rem;
    color: #fff;
    font-family: 'Black Ops One', cursive;
}

/* .arrows-left {
    position: absolute;
    top: 50%;
    left: 5%;
    transform: translateY(-50%);
}

.line-arrow {
    width: 2px;
    height: 70px;
    background-color: black;
}

.top-line {
    transform: rotate(48deg) translateY(25%);
}

.bottom-line {
    transform: rotate(-48deg) translateY(-25%);
} */

.arrows-left {
    position: absolute;
    top: 50%;
    left: 5%;
    transform: translateY(-50%) rotate(45deg);
}

.arrows-right {
    position: absolute;
    top: 50%;
    right: 5%;
    transform: translateY(-50%) rotate(-135deg);
}

.arrow {
    width: 80px;
    height: 80px;
    border-left: 2px solid #000;
    border-bottom: 2px solid #000;
    cursor: pointer;
}
<section class="slider">
  <div class="slid slid1 active">
    <div class="engine img-slid"> </div>
    <p class="slid-text">engine</p>
    <p class="number-slaid">01</p>
  </div>
  <div class="slid slid2 ">
    <div class="exhaust img-slid"></div>
    <p class="slid-text">exhaust</p>
    <p class="number-slaid">02</p>
  </div>


  <div class="arrows-slider">
    <div class="arrows-left arrow"></div>
    <div class="arrows-right arrow"></div>
  </div>

</section>
2个回答

首先,在您的场景中使用 Array.forEach() 通常不是一个好主意,因为即使您的工作已在第一个元素上完成,它也会遍历整个列表。因此,我强烈建议您使用可以中断的循环。因为在设置下一个 element.classList.active 后,列表就没有必要继续了。

您的第二个错误正如 David 所解释的那样,在到达列表的最后一个元素时没有重置回位置 0

这是一个有效示例。我在一个代码中合并了 arrows-rightarrows-left 事件行为。

const slid = [...document.querySelectorAll('.slid')];
const arrows = document.querySelectorAll('.arrows-slider .arrow');

arrows.forEach( arrow =>
{
    arrow.addEventListener('click', function(clickEvent)
    {
      var target = clickEvent.currentTarget;
        for(let i = 0; i < slid.length; i++)
        {
            if( slid[i].classList.contains('active'))
            {
                slid[i].classList.remove('active'); 
                let numberArray;
                
                if(target.classList.contains("arrows-right")) 
                {
                  numberArray = 0;
                  i++;  
                } else 
                {
                  numberArray = slid.length - 1;
                  i--;  
                } 
                
                if(slid[i] === undefined)
                  slid[numberArray].classList.add('active');
                else
                  slid[i].classList.add('active');
                  
                break;
            }
        }
    });
});
.slider {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    background-image: url('../img/mirrored_squares.png');
    height: 100vh;
}

.slid {
    position: absolute;
    width: 100%;
    height: 100vh;
    opacity: 0;
    display: none;
}

.slid.active {
    opacity: 1;
    display: block;
}

.img-slid {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 35%;
    height: 50%;
    background-size: cover;
}

.engine {
    background-image: url("../img/silnik.jpg");
}

.exhaust {
    background-image: url("../img/wydech.jpg");
}



.slid-text {
    position: absolute;
    top: 50%;
    left: 11%;
    transform: translateY(-50%);
    font-size: 8rem;
    text-transform: uppercase;
    color: green;
    font-family: 'Black Ops One', cursive;

}

.number-slaid {
    position: absolute;
    bottom: 8%;
    right: 8%;
    font-size: 2rem;
    color: #fff;
    font-family: 'Black Ops One', cursive;
}

/* .arrows-left {
    position: absolute;
    top: 50%;
    left: 5%;
    transform: translateY(-50%);
}

.line-arrow {
    width: 2px;
    height: 70px;
    background-color: black;
}

.top-line {
    transform: rotate(48deg) translateY(25%);
}

.bottom-line {
    transform: rotate(-48deg) translateY(-25%);
} */

.arrows-left {
    position: absolute;
    top: 50%;
    left: 5%;
    transform: translateY(-50%) rotate(45deg);
}

.arrows-right {
    position: absolute;
    top: 50%;
    right: 5%;
    transform: translateY(-50%) rotate(-135deg);
}

.arrow {
    width: 80px;
    height: 80px;
    border-left: 2px solid #000;
    border-bottom: 2px solid #000;
    cursor: pointer;
}
<section class="slider">
  <div class="slid slid1 active">
    <div class="engine img-slid"> </div>
    <p class="slid-text">engine</p>
    <p class="number-slaid">01</p>
  </div>
  <div class="slid slid2 ">
    <div class="exhaust img-slid"></div>
    <p class="slid-text">exhaust</p>
    <p class="number-slaid">02</p>
  </div>
  <div class="slid slid3 ">
    <div class="smoke img-slid"></div>
    <p class="slid-text">smoke</p>
    <p class="number-slaid">03</p>
  </div>
  
  <div class="arrows-slider">
    <div class="arrows-left arrow"></div>
    <div class="arrows-right arrow"></div>
  </div>
</section>
Mosia Thabo
2022-06-18

当循环遍历 slid 数组时,您将 s 定义为该数组中的每个元素:

slid.forEach(s => {

然后,您将 numberArray 定义为该元素在该数组中的索引:

let numberArray = slid.indexOf(s);

然后,您增加 numberArray

numberArray ++;

然后访问该新索引处的元素:

slid[numberArray].classList.add('active');

那么,当 s 是数组的最后一个元素时会发生什么? numberArray 将是该元素的索引,然后您将其增加到 最后一个元素 之后的元素的索引。不存在这样的元素,因此此时 slid[numberArray]undefined

到达数组末尾后,您想如何处理?无论您想如何处理,您都可以在那里实现该逻辑。

例如,如果您想在到达最后一个元素时从数组的开头重新开始,您可以检查是否位于数组末尾并重置为 0

let numberArray = slid.indexOf(s);
numberArray ++;
if (numberArray >= slid.length) {
  numberArray = 0;
}
slid[numberArray].classList.add('active');
David
2022-06-18