【问题标题】:How to avoid creating several if/statements and/or instances of function如何避免创建多个 if/语句和/或函数实例
【发布时间】:2018-03-20 15:00:17
【问题描述】:

我有这个代码:https://pastebin.com/zgJdYhzN Javascript。当滚动功能达到某个点时,它应该淡入文本,虽然这确实有效,但会有几个页面使用它,我想避免创建这个函数的多个实例。如果我可以只创建一个函数并且对于每个具有“.split”类的元素,这将对其起作用,那就更好了。

//EXECUTES ONLY ONCE
function once(fn, context) { 
    var result;
    return function() { 
        if(fn) {
            result = fn.apply(context || this, arguments);
            fn = null;
        }
        return result;
    };
}
// Usage
var split1 = once(function() {
    fadeInText(".split1");
});
var pl = once(function() {
    fadeInText(".pl");
});
var pl1 = once(function() {
    fadeInText(".pl1");
});
var smallp = once(function() {
    fadeInText(".smallp");
});
var smallp1 = once(function() {
    fadeInText(".smallp1");
});
var smallp2 = once(function() {
    fadeInText(".smallp2");
});
var smallp3 = once(function() {
    fadeInText(".smallp3");
});
var head0 = once(function() {
    fadeInText(".head0");
});

$(window).scroll(function() {

  if( $(this).scrollTop() + $(window).height() > $(".split1").offset().top) {
      split1();
  }
    if( $(this).scrollTop() + $(window).height() > $(".pl").offset().top) {
      pl();
  }
    if( $(this).scrollTop() + $(window).height() > $(".pl1").offset().top) {
      pl1();
  }
    if( $(this).scrollTop() + $(window).height() > $(".smallp").offset().top) {
      smallp();
  }
    if( $(this).scrollTop() + $(window).height() > $(".smallp1").offset().top) {
      smallp1();
  }
    if( $(this).scrollTop() + $(window).height() > $(".smallp2").offset().top) {
      smallp2();
  }
    if( $(this).scrollTop() + $(window).height() > $(".smallp3").offset().top) {
      smallp3();
  }
    if( $(this).scrollTop() + $(window).height() > $(".head0").offset().top) {
      head0();
  }
});

【问题讨论】:

  • 您真的应该将$(this)$(window)$(".split1")$(".pl")... 存储在滚动处理程序“外部”(或闭包中)的变量中。现在,您在每次调用滚动处理程序时创建 24 个 jQuery 对象(其中 16 个始终相同)。并且该处理程序将被非常经常调用。
  • 我在想我可以将它们存储在像 foreach $('class) 这样的循环中,并为它们分配一个带有各自索引的数组。
  • 请说明您的要求/问题。在评论中,您说您只想使用一个类 (.split) 而不是不同的类。那为什么你有不同的功能,每个班级一个?一类,一种功能。这是一个简单的for 循环来检查元素...

标签: javascript jquery function animation tween


【解决方案1】:

不确定我是否遗漏了您为什么需要 once 方法。你有什么理由不能做这样的事情:

var selectors = ['.one', '.two', '.three'];
var elements = {};
selectors.forEach(function(selector){
    elements[selector] = $(selector);
});

function elementOnScreen(selector) {
    if(!elements[selector]){
        return false;
    }
    return  $(window).scrollTop() + $(window).height() > elements[selector].offset().top
}

$(window).scroll(function() {
    selectors.forEach(function(selector) {
        if(elementOnScreen(selector)){
            fadeInText(selector);
            delete elements[selector];
        }
        if(Object.keys(elements).length === 0){
            $(window).off('scroll');
        }
    });
});

【讨论】:

  • 你在fadeInText(selector)之后缺少elements[selector] = undefined
  • 这是因为当scrolltop到达一定距离时,它会重复执行该功能,但我只需要它触发一次。
【解决方案2】:

只需使用循环为所有元素生成函数:

 const handlers = [".split1", ".pl" /*...*/]
   .map(s => ({ el: $(s), show: once(() => fadeInText(s)) }));

$(window).scroll(function() {
  for(const {el, show} of handlers) {
    if( $(this).scrollTop() + $(window).height() > el.offset().top) 
       show();
  }
});

您还可以为类的所有元素生成处理程序:

const handlers = $(".split").toArray()
   .map(s => ({ el: $(s), show: once(() => fadeInText(s)) }));

【讨论】:

  • 你知道我可以如何将它调整到我可以为每个我希望它作用的元素使用一个类吗?
  • @joshua 当然,如果fadeInText 也包含元素
  • 我使用了你修改后的建议,它作用于第一个元素而不是其他元素,你知道出了什么问题吗? link
  • 我还没有写过代码,所以我为什么要知道发生了什么?!
  • 我上传到jsbin
猜你喜欢
  • 2013-06-17
  • 2016-02-19
  • 1970-01-01
  • 1970-01-01
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多