javascript - 如何将 jQuery 函数转换为 JavaScript?
问题描述
我正在努力将一些东西从 jQuery 切换到 vanilla JS。我在某些方法上遇到了麻烦。我想我有一些,但有些没有。
jQuery
$(".control-ct .arrow").on("click", function () {
if ($(this).is("#left-arrow")) {
$("#testimonialSlides .customer-block.active")
.removeClass("active")
.prev(".customer-block")
.add("#testimonialSlides .customer-block:last")
.first()
.addClass("active");
} else {
$("#testimonialSlides .customer-block.active")
.removeClass("active")
.next(".customer-block")
.add("#testimonialSlides .customer-block:first")
.last()
.addClass("active");
}
});
JavaScript
let control = document.querySelector('.control-ct .arrow');
control.addEventListener('click', function() {
let activeSlides = document.querySelector('#testimonialSlides .customer-block.active');
if (control.matches('#left-arrow')) {
activeSlides.classList.remove('active')
activeSlides.prevElementSibling('.customer-block')
activeSlides.add('#testimonialSlides .customer-block:last')
activeSlides.at(0)
activeSlides.classList.add('active');
} else {
activeSlides.classList.remove('active')
activeSlides.nextElementSibling('.customer-block')
activeSlides.add('#testimonialSlides .customer-block:first')
activeSlides.at(-1)
activeSlides.classList.add('active');
}
});
let control = document.querySelector('.control-ct .arrow');
control.addEventListener('click', function() {
let activeSlides = document.querySelector('#testimonialSlides .customer-block.active');
if (control.matches('#left-arrow')) {
activeSlides.classList.remove('active')
activeSlides.prevElementSibling('.customer-block')
activeSlides.add('#testimonialSlides .customer-block:last')
activeSlides.at(0)
activeSlides.classList.add('active');
} else {
activeSlides.classList.remove('active')
activeSlides.nextElementSibling('.customer-block')
activeSlides.add('#testimonialSlides .customer-block:first')
activeSlides.at(-1)
activeSlides.classList.add('active');
}
});
#testimonialSlides {
position: relative;
}
.testimonials-2020 {
padding-top: 256px;
padding-bottom: 128px;
}
.testimonials-2020 .container-fluid {
background: #f2f5f9;
}
.testimonials-2020 .customer-block {
visibility: hidden;
opacity: 0;
display: none;
}
.testimonials-2020 .customer-block.active {
visibility: visible;
opacity: 1;
display: flex;
}
.testimonials-2020 .img-ct {
position: relative;
}
.testimonials-2020 .img-ct img {
position: absolute;
bottom: -70px;
right: 0;
display: block;
}
.testimonials-2020 .txt-ct {
padding: 80px 40px 30px 0;
}
.quote-slider h3 {
max-width: 500px;
}
.quote-slider p.quote {
font-size: 28px;
line-height: 40px;
margin: 36px 0 24px;
min-height: 96px;
}
.quote-slider p.quote-small {
margin: 36px 0 24px;
padding-right: 48px;
font-size: 20px;
line-height: 32px;
}
.quote-slider p.quote span {
color: #005fec;
font-size: inherit;
}
.quote-slider p {
font-size: 16px;
line-height: 24px;
}
.quote-slider p.name {
font-weight: 700;
}
.testimonials-2020 .control-ct {
padding-bottom: 48px;
}
.testimonials-2020 .control-ct #right-arrow {
margin-left: 22px;
}
.testimonials-2020 .control-ct .arrow {
cursor: pointer;
}
.testimonials-2020 .control-ct .arrow g {
transition: all 0.2s ease;
}
.testimonials-2020 .control-ct .arrow:hover g {
stroke: #005fec;
}
<section class="testimonials-2020">
<div class="container-fluid no-pad">
<div class="container no-pad">
<div class="quote-slider" id="testimonialSlides">
<div class="row customer-block justify-content-center" data-customer-quote="01">
<h2>One</h2>
</div>
<div class="row customer-block justify-content-center" data-customer-quote="02">
<h2>Two</h2>
</div>
<div class="row customer-block justify-content-center" data-customer-quote="03">
<h2>Three</h2>
</div>
<div class="control-ct">
<svg id="left-arrow" class="arrow" fill="none" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
<g stroke="#000a70" stroke-width="2.5">
<path d="m9 1-7 7 7 7"></path>
<path d="m2.5 8h13.5"></path>
</g>
</svg><svg id="right-arrow" class="arrow" fill="none" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg">
<g stroke="#000A70" stroke-width="2.5">
<path d="m1 8h13.5"></path>
<path d="m8 15 7-7-7-7"></path>
</g>
</svg>
</div>
</div>
</div>
</div>
</section>
解决方案
我可以看到的问题是:
jQuery 代码将处理程序连接到所有匹配的元素上。您的代码
querySelector
只使用了第一个元素。您需要使用querySelectorAll
一个循环来执行您的 jQuery 代码正在执行的操作。jQuery 的
.prev(".customer-block")
(and.next(...)
) 为您提供了一个集合,其中包含您调用它的集合中每个元素的立即前一个元素,如果它们与选择器匹配。您的代码试图将previousElementSibling
用作函数,但它是一个元素,而不是函数,并且有 o DOM 等效于“给我上一个,或者null
如果它与这个选择器不匹配”。您的选择器仍在使用
:last
and:first
,这是 jQuery 添加的东西,而不是 DOM 原生的。
以下是解决这些问题的方法:
// Loop through all matching elements
for (const control of document.querySelectorAll(".control-ct .arrow")) {
// Handle click on this element
control.addEventListener("click", function() {
// Get the active slide
let activeSlide = document.querySelector("#testimonialSlides .customer-block.active");
if (control.id === "left-arrow") { // No need for `.matches` here
// This slide is no longer active
activeSlide.classList.remove("active");
// Get the previous element
let prev = activeSlide.previousElementSibling;
// If there is none or it doesn't match, use the last instead
if (!prev || !prev.classList.contains("customer-block")) {
// No previous slide, use the last instead
const slides = document.querySelectorAll("#testimonialSlides .customer-block");
prev = slides[slides.length - 1];
}
// Make it active
prev.classList.add("active");
} else {
// This slide is no longer active
activeSlide.classList.remove("active");
// Get the next element
let next = activeSlide.nextElementSibling;
// If there is none or it doesn't match, use the first instead
if (!next || !next.classList.contains("customer-block")) {
// `querySelector` only returns the first match, not a list like `querySelectorAll` does
next = document.querySelector("#testimonialSlides .customer-block");
}
next.classList.add("active");
}
});
}
或者实际上,我认为我们可以简化上一个/下一个部分:
// Loop through all matching elements
for (const control of document.querySelectorAll(".control-ct .arrow")) {
// Handle click on this element
control.addEventListener("click", function() {
// Get all slides and the active slide
const slides = [...document.querySelectorAll("#testimonialSlides .customer-block")];
// Get the active slide's index
let index = slides.findIndex(slide => slide.classList.contains("active"));
// This slide is no longer active
slides[index].classList.remove("active");
// Make the new one active via its index (with wrap-around)
index = (index + (control.id === "left-arrow" ? -1 : 1) + slides.length) % slides.length;
slides[index].classList.add("active");
});
}
现场示例:
// Loop through all matching elements
for (const control of document.querySelectorAll(".control-ct .arrow")) {
// Handle click on this element
control.addEventListener("click", function() {
// Get all slides and the active slide
const slides = [...document.querySelectorAll("#testimonialSlides .customer-block")];
// Get the active slide's index
let index = slides.findIndex(slide => slide.classList.contains("active"));
// This slide is no longer active
slides[index].classList.remove("active");
// Make the new one active via its index (with wrap-around)
index = (index + (control.id === "left-arrow" ? -1 : 1) + slides.length) % slides.length;
slides[index].classList.add("active");
});
}
.customer-block {
display: inline-block;
width: 20px;
text-align: center;
color: grey;
border: 1px solid transparent;
}
.customer-block.active {
font-weight: bold;
color: green;
border: 1px solid green;
}
<div class="control-ct">
<input class="arrow" type="button" id="left-arrow" value="<">
<input class="arrow" type="button" id="right-arrow" value=">">
</div>
<div id="testimonialSlides">
<div class="customer-block active">1</div>
<div class="customer-block">2</div>
<div class="customer-block">3</div>
<div class="customer-block">4</div>
<div class="customer-block">5</div>
</div>
推荐阅读
- java - 尝试保存和加载基于文本的 ui 游戏时如何修复 java.io.NotSerializableException?
- c# - 如何使用 StreamReader 并从文本文件的某些部分读取?
- python - 用 Python 中另一个列表中的值更新一个列表
- javascript - 在 dropdownList 中调用 JS 函数
- loops - 如何在 BigQuery 中引用另一个表作为案例中多个喜欢的来源?
- javascript - 从 API 调用中跳过未定义的元素
- laravel - 如何将 spatie laravel 存储的备份上传到谷歌驱动器?
- python - 将 exec 进程中的标准输出存储到变量中
- c++ - 如何知道协程分配器的对齐要求?
- javascript - Firebase 函数问题:(未定义)对象不可迭代(无法读取属性 Symbol(Symbol.iterator))