【问题标题】:Why index of forEach is always 0 in array returned by IntersectionObserver?为什么 IntersectionObserver 返回的数组中 forEach 的索引始终为 0?
【发布时间】:2019-12-08 16:37:39
【问题描述】:

我正在使用 IntersectionObserver API。

输入特定部分时,background-color 会更改。
为了处理这个问题,我必须在此处获取IntersectionObserverEntry 数组中输入条目的索引,称为entries

我使用forEach 方法获取条目的索引,但奇怪的是它总是将索引设置为0。但是当我通过获取的索引访问条目时,它运行良好。

const intersectionObserver = new IntersectionObserver(entries => {
  entries.forEach((entry,index) => {
    if(entry.isIntersecting) {
      console.log('Intersecting',index);
      entry.target.className = entry.target.className.replace('hidden','fadeIn');
      changeBackgroundColor(entry.target.dataset.color);
      changeLogoColor(entry.target.dataset.theme);
    } else {
      console.log('Leave',index);
      entry.target.className = entry.target.className.replace('fadeIn','hidden');
    }
  });
});
const fadeInElemes = document.querySelectorAll('.hidden');
fadeInElemes.forEach((fadeInElem) => intersectionObserver.observe(fadeInElem));

结果如下...

相交0
离开 0
留下0.....

我的代码有什么问题?为什么 index 总是为 0,但通过获取的 index 访问会得到正确的元素?

编辑

Log of entries

【问题讨论】:

  • 恕我直言,您的问题不是 indexOf() 行为,请尝试记录数组 entries
  • @MosèRaguzzini 我为此进行了编辑。
  • Ok indexOf 失败,因为对象比较浅,只返回找到的第一个项目
  • 不,尝试迭代并记录 foreach 第二个参数(索引),您可能不需要 indexOf()
  • 因为 IntersectionObserver 回调中的条目数组仅包含一项,并且fadeInElemes 正在设置观察者 N 次?所以每个 Intersecting 0, Leave 0, Leave 0 都被fadeInElems foreach observe call调用

标签: javascript arrays intersection-observer


【解决方案1】:

您可以在forEach中访问entry的索引,无需使用indexOf()。

entries.forEach((entry, i) => console.log(i))

MDN 网络文档有很好的文档,有很好的例子,你大部分时间都可以在那里找到你需要的东西,here is the link for the forEach method

【讨论】:

  • 不,我编辑了。它不工作。查看我编辑的问题
  • 只有第一次进入forEach时才真正起作用。但更深一点,在entry.isIntersection 内部,i 每次都是 0。
【解决方案2】:

比较对象时,IndexOf 可能无法正常工作:

const user1 = {name : "nerd", org: "dev"};
const user2 = {name : "nerd", org: "dev"};
const eq = user1 == user2;
console.log(eq); // gives false

const myArr = [user1, user2];
console.log(myArr.indexOf(user1)); // gives 0 because same instance
console.log(myArr.indexOf(user2)); // gives 1 because same instance

const myArr2 = [{name : "nerd", org: "dev"}, {name : "nerd", org: "dev"}];
console.log(myArr2.indexOf(user1)); // gives -1 because not same instance
console.log(myArr2.indexOf(user2)); // gives -1 because not same instance

如果IndexOf() 是returnig 0,则表示当前条目实例与位置0 相同。

看看你是如何创建你的数组的,也许条目在数组中包含相同的实例。

【讨论】:

  • 即使在rev 2 他们确实在使用 indexOf,您的回答也没有任何意义。如果没有重复条目,forEach((el, i, arr) => arr.indexOf(el) === i) 将始终只生成 true,这在 IntersectionObserver 的回调中是不可能的
  • @Kaiido Array.indexOf() 返回第一个找到的元素的索引-1。它不返回布尔值,伙计。
  • 我指的是console.log('Leave',entries.indexOf(entry)),总是返回0
  • 因为它总是在console.log中返回0,每次迭代
  • Mhaa... 如果它返回 0,因为它已被找到,在索引 0 处。所以你的回答是因为两个对象文字不是相同的对象而没有找到它们的对象是完全关闭的。如果你在某种程度上是对的,那么他们将有 -1。
【解决方案3】:

您正在记录不是来自元素数组的条目的索引

fadeInElemes.forEach((fadeInElem) => intersectionObserver.observe(fadeInElem));

这是您获得实际寻找的索引的地方

【讨论】:

    【解决方案4】:

    您可以在观察者注册元素之前将索引链接到元素的属性。 重要!您的属性名称应该是唯一的,以避免覆盖标准属性。

    请阅读下面的 cmets,我已将保存索引的代码行(18 行)和读取(5 行)分开。

    const observer = new IntersectionObserver((entries, observer) => {
        entries.forEach(entry => {
    
            // read index from element’s property
            let index = entry.target.elems_index;
    
            if (entry.isIntersecting) {
                console.log(index, entry.target, 'is visible');
            } else {
                console.log(index, entry.target, 'is hidden');
            }
        })
    });
    let elems = document.querySelectorAll('.elem');
    elems.forEach((elem, index) => {
    
        // save index as element’s property before register the element in observer
        elem.elems_index = index;
    
        observer.observe(elem);
    });
    

    在那里打开笔的控制台以查看结果:https://codepen.io/rafaylik/pen/jOMQQdd

    【讨论】:

      【解决方案5】:

      您可以根据观察到的元素检查入口目标。所以是这样的:

      const elementList = document.querySelectorAll('.list-of-elements')
      
      const observer = new IntersectionObserver((entries) => {
        for(const entry of entries) {
          if (entry.isIntersecting) {
            // compare target to element list
            const currentIndex = elementList.indexOf(entry.target)
          }
        }
      })
      
      Array.from(elementList).forEach(element => observer.observe(element))
      

      【讨论】:

        猜你喜欢
        • 2021-05-01
        • 1970-01-01
        • 2013-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多