将额外的参数传递给IntersectionObserver?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将额外的参数传递给IntersectionObserver?相关的知识,希望对你有一定的参考价值。

我如何将额外的参数传递给IntersectionObserver?我正在尝试为Vue创建一个lazyload插件。它工作正常,但我也希望能够调用提供的指令函数。

const lazyload = {
    install(Vue) {
        const observer = new IntersectionObserver((entries) => {
            entries.forEach((entry) => {
                if (entry.intersectionRatio > 0) {
                    console.log('In viewport');
                }
            });
        });

        Vue.directive('lazy', {
            inserted(element) {
                observer.observe(element);
            }
        });
    }
};

这意味着在插入函数中我将binding设置为第二个参数。

inserted(element, binding)

我如何通过这个绑定,以便我可以在我的IntersectionObserver回调中使用它?

最后它应该能够看起来像这样:

<div class="col-sm-6" v-lazy="fire">
答案

您可以使用binding.value访问指令的参数:

// html
<div v-lazy="0.5"></div>

// script
Vue.directive('lazy', {
  inserted(el, binding) {
    console.log(binding.value) // 0.5
  }
})

为每个指令用法创建一个新的IntersectionObserver可能是有意义的。例如,您可能希望一个div具有与另一个div不同的滚动阈值。在inserted回调中,我将使用指令参数中指定的选项创建观察者:

const makeObserver = options => new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    console.log({entry, ratio: options.threshold})
    if (entry.intersectionRatio >= options.threshold) {
      console.log('In viewport', {entry, ratio: options.threshold});
    }
  });
}, options);

Vue.directive('lazy', {
  inserted(el, binding) {
    const options = binding.value || {}
    const observer = makeObserver(options)
    observer.observe(el)
  }
})

然后,您可以使用该指令为div创建具有不同参数的多个IntersectionObservers:

<div style="height: 100px; background: gray" v-lazy="{root: null, threshold: 0.1}"></div>
<div style="height: 200px; background: lightgray" v-lazy="{root: null, threshold: 1}"></div>

demo

另一答案

如果您确实希望将值作为额外参数传递,则可以使用Function.bind,但是您必须为每个指令调用创建单独的IntersectionObserver。

我在这里推荐一个WeakMap,并让回调检查映射以获得正确的处理程序。就像是:

const lazyload = {
  install(Vue) {
    const handlers = new WeakMap();
    const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          console.log('In viewport');
          handlers.get(entry.target)();
        }
      });
    });

    Vue.directive('lazy', {
      inserted(element, binding) {
        handlers.set(element, binding.value);
        observer.observe(element);
      }
    });
  }
};

(我没有使用Vue,所以我不确定这会逐字逐句)

顺便说一句,我把entry.intersectionRatio > 0换成了entry.isIntersecting。这可能是一个错误,但我在Chrome 65中看到,当滚动速度非常慢时,你可以得到entry.intersectionRatio === 0 && entry.isIntersecting === truehttps://jsfiddle.net/3jgm0ch7/2/

以上是关于将额外的参数传递给IntersectionObserver?的主要内容,如果未能解决你的问题,请参考以下文章

如何将额外的额外参数传递给批处理文件?

将额外的参数传递给IntersectionObserver?

将额外参数传递给 usort 回调

将额外参数传递给异步映射

将额外参数传递给异步映射

如何使用 withColumn 将额外的参数传递给 UDF