如何在JavaScript中仅调用一次函数

5

注意:我需要使用纯javascript来实现此功能,我知道jquery中有一个.one()方法可以做到这一点,但我需要在纯javascript中获得相同的输出。

场景:我试图在用户滚动并达到页面的3/4部分或更多时调用一个函数,但当用户达到该部分时出现问题,我们都知道他们不能完美像素,所以,在满足条件后,该函数将每个像素滚动执行。

我希望只有满足条件后才会执行一次,然后在页面底部添加一个部分,然后再次让用户到达底部,函数应该只被执行一次,依此类推...

片段:

var colors = ['skyblue', 'powderblue', 'lightgreen', 'indigo', 'coral'];

var addPage = function() {
  var page = document.createElement('div');
  page.classList.add('page');
  page.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
  document.body.append(page);
  console.log('added a new page');
}

var scrollAndAdd = function() {
  if (window.scrollY < (window.innerHeight * (3 / 4))) {
    // execute addPage only once for each attempt; it's creating infinite pages
    addPage();
  }
}

window.addEventListener('scroll', scrollAndAdd);
* {
  margin: 0;
  padding: 0;
}

.page {
  height: 100vh;
}
<div class='page' style='background-color: lightgreen'></div>
<div class='page' style='background-color: skyblue'></div>


2
你需要记住你执行了方法。添加一个全局变量,并在添加额外页面时重置。 - Hans Kesting
您是希望只添加一个页面,永远不再添加其他页面呢?还是有某些条件下可以再次添加页面?用户是否需要再次向上滚动,或者有其他逻辑需考虑? - trincot
@trincot 假设有两个页面,因此正文的总高度应为 200vh(因为1页是 100vh),假设用户滚动到了 190vh 甚至更低,那么就会添加一个新页面,正文的总高度现在变成了 300vh,现在用户滚动到了 290vh 以及更多,另一页应该被添加,以此类推... - Towkir
就像@HansKesting所说,如果您需要记住页面状态,请将该状态放入全局变量中以在函数中读取和更新。在脚本中的函数上面定义您的状态,并赋予它任何初始值。 - Dave S
您可以使用动态阈值来确定是否加载另一页。由于页面大小固定为100vh,因此当您到达190时,请更新页面以显示新内容,并将您的阈值增加100。现在,只有当您超过该行时才会加载新页面。 - Potato
addPage 的末尾添加 addPage = () => {}; - Bergi
3个回答

4
你不需要逻辑来运行函数仅一次;相反,使用另一个表达式来确定是否添加页面。一旦页面被添加,同样的表达式在更多滚动完成之前不应再次求值。
注:我还稍微改变了随机选择逻辑。

var colors = ['powderblue', 'lightgreen', 'indigo', 'coral', 'skyblue'];

var addPage = function() {
  var page = document.createElement('div');
  page.classList.add('page');
  // Make sure the same color is not selected twice in sequence:
  var colorIndex = Math.floor(Math.random() * (colors.length-1));
  var color = colors.splice(colorIndex,1)[0];
  colors.push(color);
  page.style.backgroundColor = color;
  document.body.append(page);
}

var scrollAndAdd = function() {
  if (window.scrollY > document.body.clientHeight - window.innerHeight - 10) {
    addPage();
  }
}
window.addEventListener('scroll', scrollAndAdd);
* {
  margin: 0;
  padding: 0;
}

.page {
  height: 100vh;
}
<div class='page' style='background-color: lightgreen'></div>
<div class='page' style='background-color: skyblue'></div>


请检查这行代码 var colorIndex = Math.floor(Math.random() * (colors.lengt-1));,难道不应该是 length 吗? - Towkir
我的意思是有一个打字错误,应该是 length-1 而不是 lengt-1 - Towkir
啊,没错 :) 已经修复了。 - trincot
浏览您的答案是我在SO上最喜欢的愉快活动之一。 - deblocker
哇,听到这样的话真是太好了。谢谢! - trincot

0

那么,加上本地标志如何?

var colors = ['skyblue', 'powderblue', 'lightgreen', 'indigo', 'coral'];


const localCurry = function(func, immediateAction) {
  var flag;
  return  function() {
    var context = this, args = arguments;
    var callNow = immediateAction && !flag;
    flag = true;
    if (callNow) func.apply(context, args);
  }
}


var addPage = localCurry(function() {
  var page = document.createElement('div');
  page.classList.add('page');
  page.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
  document.body.append(page);
  console.log('added a new page');
}, true);

var scrollAndAdd = function() {
  var a = document.body.clientHeight - window.innerHeight * (5 / 4)
  if (window.scrollY > a) {
    addPage();
  }
}

window.addEventListener('scroll', scrollAndAdd);

现在你可以根据定时器或自定义逻辑重置标志。


0

希望这能对你有所帮助:

var colors = ['skyblue', 'powderblue', 'lightgreen', 'indigo', 'coral'];

var addPage = function() {
  var page = document.createElement('div');
  page.classList.add('page');
  page.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
  document.body.append(page);
  console.log('added a new page');
}

var scrollAndAdd = function() {
  var a = document.body.clientHeight - window.innerHeight * (5 / 4)
  if (window.scrollY > a) {
    addPage();
  }
}

window.addEventListener('scroll', scrollAndAdd);
* {
  margin: 0;
  padding: 0;
}

.page {
  height: 100vh;
}
<div class='page' style='background-color: lightgreen'></div>
<div class='page' style='background-color: skyblue'></div>


这正是我所面临的问题,这与我提供的有何不同? - Towkir
@TowkirAhmed,请注意这是不同的。看一下变量 a - trincot
我做了,你是对的,但第一次它创建了太多像我的页面,会点赞这个答案。 - Towkir
@trincot,谢谢你指出我的代码是正确的,而且我比你更早地发布了它 ;) - qiAlex
确实,@qiAlex,但那只是几秒钟的事情--好的想法经常同时浮现;-) 我会投票支持你的。 - trincot
谢谢@trincot,你的回答比我的好,你还改进了随机选择逻辑。我今天已经达到了点赞限制,但我稍后会给你点赞。 - qiAlex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接