在javascript中对多个html类使用一个函数(通过阅读更多按钮扩展文本)



堆栈溢出的第一篇文章:)

我正在尝试在我所有的 HTML 按钮上放置一个特定的功能,到目前为止,在尝试了 2 天后,我还没有找到任何有效的功能(编码新手)。

我基本上要做的是一个"阅读更多"按钮,它在单击时显示文本。到目前为止,.getElementsByClassName和.querySelectorAll都没有工作。如果我只使用一个 #id 的代码,它可以正常工作,但我知道必须有一种更好的方法将一个函数用于多个元素,而不是拥有多个 id 并单独为每个 id 使用该函数。我也尝试了一个forEach()循环,但它没有做任何事情。此外,我已经尝试了readMoreBtn[length].addEventListener('click', () => {}),但这也没有用。

正如我所说,它适用于.getElementByIdquerySelector,但不适用于.getElementsByClassName.querySelectorAll.如果我使用querySelectorAll,第一个按钮有效,但其他按钮无效。

由于我有兴趣让它与类而不是 id 一起使用,所以我从 HTML 中删除了 id 属性。

我不会发布我的完整 HTML,因为它很长,但带有按钮的容器如下所示:

<div class="main-container">


<h6 class="main-artist"><em class="main-emph">content</em>content</h6>

<p class="main-p"><span class="moreText"> Lorem ipsum </span></p>
<button class="readMore">read more</button>
</div>  

和JS:

const readMoreBtn = document.getElementsByClassName('.readMore');
const text = document.querySelector('.main-p');
readMoreBtn.addEventListener('click', () => {
text.classList.toggle('show-more');
if(readMoreBtn.innerHTML === "read more") {
readMoreBtn.innerHTML = "read less"
} else {
readMoreBtn.innerHTML = "read more"
}
})

感谢您的帮助,如果您对如何改进我的提问方式有任何建议,请拍摄。

编辑:我有多个按钮,所有按钮都有一个独特的文本。我的目标是让按钮以某种方式在其下方显示其独特的文本。这是另一个HTML来显示我的意思:

<div class="main-container">

<h6 class="main-artist"><em class="main-emph">content</em>content</h6>
<p class="main-p"><span class="moreText"> Lorem ipsum </span></p>
<button class="readMore">read more</button>
</div> 
<div class="main-container">

<h6 class="main-artist"><em class="main-emph">content</em>content</h6>
<p class="main-p"><span class="moreText"> Messi GOAT </span></p>
<button class="readMore">read more</button>
</div> 
<div class="main-container">

<h6 class="main-artist"><em class="main-emph">content</em>content</h6>
<p class="main-p"><span class="moreText"> Ipsum Lorem </span></p>
<button class="readMore">read more</button>
</div> 

使用此JS代码,我只能扩展第一个main-p,而不能扩展其他。

const yourFunction = (e)=>{

const text = document.querySelector('.main-p');
text.classList.toggle('show-more');
if(e.target.innerHTML === "read more") {
e.target.innerHTML = "read less"
} else {
e.target.innerHTML = "read more"
}

}

在我的脑海中,有两种解决方案可能有效:

  1. 我必须以某种方式在 HTML 中将每个button连接到他们的main-p?我试过了,但没有用。

  2. 在 JS 中使用循环。

这两者之一可能吗?蒂亚

有很多方法可以做到这一点。 试试这个。

const yourFunction = (e) => {
const text = document.querySelector('.main-p');
text.classList.toggle('show-more');
if (e.target.innerHTML === "read more") {
e.target.innerHTML = "read less"
} else {
e.target.innerHTML = "read more"
}
}
<div class="main-container">
<h6 class="main-artist"><em class="main-emph">content</em>content</h6>
<p class="main-p"><span class="moreText"> Lorem ipsum </span></p>
<button class="readMore" onclick="yourFunction(event)">read more</button>
</div>

getElementsByClassName()返回一个 HTMLCollection。

querySelectorAll()返回一个 NodeList。

相比之下,querySelector()getElementById()返回一个 DOM 元素。

这些类型中的每一种的访问和操作方式都不同。您将 HTMLCollection 和 NodeList 视为一个元素。

访问 HTMLCollection 和 NodeList 中每个项的一种方法是首先使用Array.from()将它们转换为数组,然后在生成的数组上使用forEach()来迭代每个元素,在本例中,向元素添加一个 click 事件处理程序:

const readMoreBtn = document.getElementsByClassName('readMore');
const text = document.querySelectorAll('.main-p');
console.log(Array.from(text));
Array.from(readMoreBtn).forEach(function(elem) {
elem.addEventListener('click', ({target}) => {
target.textContent = ('read more' === target.textContent) ? 'read less' : 'read more';
});
});
<p class="main-p"><span class="moreText"> Lorem ipsum 1</span></p>
<button class="readMore">read more</button>
<p class="main-p"><span class="moreText"> Lorem ipsum 2</span></p>
<button class="readMore">read more</button>
<p class="main-p"><span class="moreText"> Lorem ipsum 3</span></p>
<button class="readMore">read more</button>

我更喜欢使用更少的JS,但更多的CSS。(更灵活)

例如,只需在容器(父级)中添加.is-acitve,只需在CSS中设置样式

const buttons = document.querySelectorAll('.main-container .readMore');
const setContainerActive = (el) => {
el.target.closest('.main-container').classList.toggle('is-active')
}
Array.from(buttons).forEach((el) => {
el.addEventListener('click', setContainerActive)
});
.main-container {
/* Defaults */
}
.main-container.is-active {
/* Active */
background: red;
}
/* Example */
.main-container .show-is-active { display:none; }
.main-container.is-active .show-is-active { display: block; }
.main-container .hide-is-active { display:block; }
.main-container.is-active .show-hide-active { display: none; }
<div class="main-container">
<h6 class="main-artist"><em class="main-emph">content</em>content</h6>
<p class="main-p"><span class="moreText"> Lorem ipsum </span></p>
<button class="readMore"><span class="show-is-active">read less</span><span class="show-hide-active">read more</span></button>
</div>

HTML:

<div class="main-container">
<h6 class="main-artist">
<em class="main-emph">content</em> content
</h6>
<p class="main-p">
<span class="moreText"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tempora aliquid at, provident molestiae necessitatibus ullam culpa debitis, dolorum quas accusamus quidem iusto eaque omnis veniam. Delectus quo saepe enim voluptatum! </span>
</p>
<button class="readmore">Read more</button>
</div> 

<div class="main-container">
<h6 class="main-artist">
<em class="main-emph">content</em>content
</h6>
<p class="main-p">
<span class="moreText"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tempora aliquid at, provident molestiae necessitatibus ullam culpa debitis! </span>
</p>
<button class="readmore">Read more</button>
</div>

<div class="main-container">
<h6 class="main-artist">
<em class="main-emph">content</em>content
</h6>
<p class="main-p">
<span class="moreText"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tempora aliquid at, provident molestiae necessitatibus ullam culpa debitis, dolorum quas accusamus quidem iusto eaque omnis veniam. Delectus quo saepe enim voluptatum! </span>
</p>
<button class="readmore">Read more</button>
</div>

JS文件位置: 如果您的 js 文件在<head></head>中,则必须让它等待文档加载,否则如果在文档完全加载之前执行 js 文件,则document.querySelectAll();将不起作用。您将收到控制台错误。延迟 js 文件 在 head 中

<head>
<script src="your-js-file-name.js" defer></script>
</head>

或者将 js 文件放在文档末尾的</body>close 标记之前。

<body>

<scrpit src="your-js-file-name.js"></script>
</body>

.JS:

let btn = document.querySelectorAll('.readmore');
let mainText = document.querySelectorAll('.main-p');
let container = document.querySelectorAll('.main-container');
// console.log(btn);
// console.log(mainText);
// console.log(container);
btn.forEach((i) => {
i.addEventListener('click', (evt) => {
// console.log(evt.target.previousElementSibling);
let moreContent = evt.target.previousElementSibling;
let button = evt.target;
// console.log(button);
// console.log(moreContent);
if (moreContent.style.visibility != 'visible') {
console.log("Style not present. Running code block below");
moreContent.style.visibility = 'visible';
evt.target.innerHTML = 'Read less';
} else {
console.log('Style present. Removing and replacing with default style  with code block below');
moreContent.style.visibility = 'hidden';
evt.target.innerHTML = 'Read mess';
}
})
});

.CSS:visibility: hidden;仍将允许元素占用它在文档中占用的空间。如果这不理想,则切换 css 和 js 以使用display: none;display: block;。如果需要在.main-p元素上进行平滑过渡,也可以采用其他方法来处理它。

.main-container {
border-bottom: 1.5px solid blue;
padding-bottom: 10px;
}
.main-p {
color: white;
background-color: #333;
padding: 15px;
visibility: hidden; 
}


let btn = document.querySelectorAll('.readmore');
let mainText = document.querySelectorAll('.main-p');
let container = document.querySelectorAll('.main-container');
// console.log(btn);
// console.log(mainText);
// console.log(container);
btn.forEach((i) => {
i.addEventListener('click', (evt) => {
// console.log(evt.target.previousElementSibling);
let moreContent = evt.target.previousElementSibling;
let button = evt.target;
// console.log(button);
// console.log(moreContent);
if (moreContent.style.visibility != 'visible') {
console.log("Style not present. Running code block below");
moreContent.style.visibility = 'visible';
evt.target.innerHTML = 'Read less';
} else {
console.log('Style present. Removing and replacing with default style  with code block below');
moreContent.style.visibility = 'hidden';
evt.target.innerHTML = 'Read more';
}
})
});
.main-container {
border-bottom: 1.5px solid blue;
padding-bottom: 10px;
}
.main-p {
color: white;
background-color: #333;
padding: 15px;
visibility: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="app.js" defer></script>
<title>Document</title>
</head>
<body>

<div class="main-container">
<h6 class="main-artist">
<em class="main-emph">content</em> content
</h6>
<p class="main-p">
<span class="moreText"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tempora aliquid at, provident molestiae necessitatibus ullam culpa debitis, dolorum quas accusamus quidem iusto eaque omnis veniam. Delectus quo saepe enim voluptatum! </span>
</p>
<button class="readmore">read more</button>
</div> 

<div class="main-container">
<h6 class="main-artist">
<em class="main-emph">content</em>content
</h6>
<p class="main-p">
<span class="moreText"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tempora aliquid at, provident molestiae necessitatibus ullam culpa debitis! </span>
</p>
<button class="readmore">read more</button>
</div>

<div class="main-container">
<h6 class="main-artist">
<em class="main-emph">content</em>content
</h6>
<p class="main-p">
<span class="moreText"> Lorem ipsum dolor, sit amet consectetur adipisicing elit. Tempora aliquid at, provident molestiae necessitatibus ullam culpa debitis, dolorum quas accusamus quidem iusto eaque omnis veniam. Delectus quo saepe enim voluptatum! </span>
</p>
<button class="readmore">read more</button>
</div>
</body>
</html>

希望这对您和其他有类似问题需要解决的人有所帮助。 :)

最新更新