香草JS迭代div innerHTML,以便以设定的间隔显示和隐藏



尝试使用vanilla JS获取包含div的具有特定类名的div,然后使用setTimeout,显示第一个div,然后隐藏它,然后显示下一个并重复。

我无法使用 IIFE 实现这一目标,并且可以在如何最好地接近的正确方向上使用推动。

目前 hello 继续显示何时应该隐藏,然后再见应该显示下一个,依此类推。

function iterateText() {
	var textContainer = document.getElementsByClassName("iterateText")[0];
	var items = textContainer.querySelectorAll("div");
// HIDE ALL TEXT
for(var i = 0; i < items.length; i++) {
//itemsArr.push(items[i]);
items[i].classList.add("hide");
}

// SHOW TEXT ONE AT A TIME
for (var i = 0; i < items.length; i++) {
		
(function(i) {
		  hideThis(items[i], i);
setTimeout(function() {
			if(items[i].classList.contains("hide")) {
			 	items[i].classList.remove("hide");
				items[i].classList.add("show");
				
			} 
}, 1000 * i);
			//hideThis(items[i], i);
})(i);
	  
};
	
}

function hideThis(e,i) {
	setTimeout(function(i) {
		e.classList.remove("show");
		e.classList.add("hide");
	}, 1200 * i);
}
iterateText();
.randomizeText {
display: block;
}
.randomizeText div {
display: none;
}
/*
.randomizeText div:not(:first-child) {
display: none;
visibility: hidden;
}
*/
.randomizeText div {
	opacity: 1;
	  transition: all 1s ease-in-out;
}
.show {
display: block!important;
opacity: 1;
}
.hide {
display: none!important;
opacity
<div class="iterateText">
<div>Hello</div>
<div>Goodbye</div>
<div>Good afternoon</div>
<div>Good evening</div>
</div>

如果我清楚地理解你,这可能是你搜索的:

function showItem(elem) {
if(elem.classList.contains("hide")) {
elem.classList.remove("hide");
elem.classList.add("show");
}
}
function hideItem(elem) {
if(elem.classList.contains("show")) {
elem.classList.remove("show");
elem.classList.add("hide");
}
}
function iterateText() {
var textContainer = document.getElementsByClassName("iterateText")[0];
var items = textContainer.querySelectorAll("div");
/* this part of code may be optimized */
items.forEach((item, index) => {
item.classList.add("hide"); // hide all elements
// I used `bind` function instead of creating a lot of similar functions
// more about `bind`: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind
setTimeout(showItem.bind(null, item), 1000 * index       );
setTimeout(hideItem.bind(null, item), 1000 * index + 1000);
});
/* end of part*/
}

iterateText();

毕竟,在循环中创建大量计时器是个坏主意。最好改用setInterval

优化代码:

items = Array.from(items).reverse(); // reverse it for `pop` method
items.forEach(item => item.classList.add("hide")); // hide all elements
if (items.length > 0) {
var timer;
var current = items.pop();
showItem(current);
timer = setInterval(function() {
hideItem(current); // hide current item
if (items.length > 0) {
current = items.pop();
showItem(current); // and show next one
} else {
// don't forget to stop timer after end.
// this `else` branch may be used as callback function after animation
clearInterval(timer);
}
}, 1000);
}

优化的最终版本:

function showItem(elem) {
if(elem.classList.contains("hide")) {
elem.classList.remove("hide");
elem.classList.add("show");
}
}
function hideItem(elem) {
if(elem.classList.contains("show")) {
elem.classList.remove("show");
elem.classList.add("hide");
}
}
function iterateText() {
var textContainer = document.getElementsByClassName("iterateText")[0];
var items = textContainer.querySelectorAll("div");
items = Array.from(items).reverse();
items.forEach(item => item.classList.add("hide"));
if (items.length > 0) {
var timer;
var current = items.pop();
showItem(current);
timer = setInterval(function() {
hideItem(current);
if (items.length > 0) {
current = items.pop();
showItem(current);
} else {
clearInterval(timer);
}
}, 1000);
}
}
iterateText();
.randomizeText {
display: block;
}
.randomizeText div {
display: none;
}
.randomizeText div {
	opacity: 1;
	  transition: all 1s ease-in-out;
}
.show {
display: block!important;
opacity: 1;
}
.hide {
display: none!important;
opacity: 0;
}
<div class="iterateText">
<div>Hello</div>
<div>Goodbye</div>
<div>Good afternoon</div>
<div>Good evening</div>
</div>

这是我在看到你的回复之前想到的。它可以工作,但仍然依赖于设置超时。

function iterateText() {
	var textContainer = document.getElementsByClassName("iterateText")[0];
	var items = textContainer.querySelectorAll("span");
// HIDE ALL TEXT
for(var i = 0; i < items.length; i++) {
//itemsArr.push(items[i]);
items[i].style.display = "none";
}

// SHOW TEXT ONE AT A TIME
for (var i = 0; i < items.length; i++) {
(function(i) {
		 showText(items[i], 1200 * i, function() {
		 	hideText(items[i],1000)
		 })
})(i);
};
}

function showText(value, interval, cb) {
	setTimeout(function() {
		fadeIn(value);
		typeof cb === 'function' && cb();
	}, interval);
}
function hideText(value, interval, cb) {
	setTimeout(function() {
		fadeOut(value);
		typeof cb === 'function' && cb();
	}, interval);
}
iterateText();
// FADEOUT
function fadeOut(el){
el.style.opacity = 1;
(function fade() {
if ((el.style.opacity -= .1) < 0) {
el.style.display = "none";
} else {
requestAnimationFrame(fade);
}
})();
}
// FADE IN
function fadeIn(el, display){
el.style.opacity = 0;
el.style.display = display || "block"; // default if not specified
(function fade() {
var val = parseFloat(el.style.opacity);
if (!((val += .1) > 1)) {
el.style.opacity = val;
requestAnimationFrame(fade);
}
})();
}
.iterateText span {
	min-width: 100%;
	height: auto;
}
<div class="iterateText">
<span>Hello</span>
<span>Goodbye</span>
<span>Good afternoon</span>
<span>Good evening</span>
</div>

如果我正确理解您的问题,那么您可以使用与我在下面演示的相同的方法。基本上,您只需要在for循环中使用IIFE。IIFE 将调用setTimeout,同时允许您在正确的上下文中访问i(通过将其作为局部变量传递j(。

//store the elements in a variable
var items = document.querySelectorAll('.iterateText div');
//loop the elements
for (var i = 0; i < items.length; i++) {
//use IIFE within loop so you dont lose scope
(function(j) {
setTimeout(function() {
if (items[j - 1] != null) {
items[j - 1].style.display = 'none';
}
items[j].style.display = 'inline';
}, 1000 * j)
}(i))
}
/*make all child divs non-visible by default*/
.iterateText div {
display: none
}
<div class="iterateText">
<div>Hello</div>
<div>Goodbye</div>
<div>Good afternoon</div>
<div>Good evening</div>
</div>

就个人而言,由于其简洁的性质,我认为这段代码比接受的代码更容易调试 - 但这只是我的意见!希望对您有所帮助。

最新更新