admin管理员组

文章数量:1426091

I am using the IntersectionObserver API.

When a specific section is entered, background-color is changed.
To handle this, I have to obtain the index of an entered entry in the array of IntersectionObserverEntry called entries here.

I used forEach method to get the index of the entry, but it strangely always set index as 0. But when I access entry by obtained index, it works well.

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));

Result is below...

Intersecting 0
Leave 0
Leave 0 .....

What is wrong with my code? Why index is always 0, but access by obtained index results in the right element?

EDIT

Log of entries

I am using the IntersectionObserver API.

When a specific section is entered, background-color is changed.
To handle this, I have to obtain the index of an entered entry in the array of IntersectionObserverEntry called entries here.

I used forEach method to get the index of the entry, but it strangely always set index as 0. But when I access entry by obtained index, it works well.

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));

Result is below...

Intersecting 0
Leave 0
Leave 0 .....

What is wrong with my code? Why index is always 0, but access by obtained index results in the right element?

EDIT

Log of entries

Share Improve this question edited Jul 31, 2019 at 8:50 Kaiido 137k14 gold badges260 silver badges326 bronze badges asked Jul 31, 2019 at 8:05 undefinedundefined 1,1782 gold badges20 silver badges33 bronze badges 12
  • IMHO the point of your issue isn't indexOf() behavior, try to log the array entries – Mosè Raguzzini Commented Jul 31, 2019 at 8:10
  • @MosèRaguzzini I edited for that. – undefined Commented Jul 31, 2019 at 8:12
  • Ok indexOf is failing because objects are shallow pared and returns only the first item found – Mosè Raguzzini Commented Jul 31, 2019 at 8:14
  • 1 Nope, try to iterate and log foreach second parama (Index), you probably do not need indexOf() – Mosè Raguzzini Commented Jul 31, 2019 at 8:16
  • 1 Because entries array in callback of IntersectionObserver contain only one item and fadeInElemes are setting the observer N-times? So each Intersecting 0, Leave 0, Leave 0 is called by fadeInElems foreach observe call – dKorosec Commented Jul 31, 2019 at 8:31
 |  Show 7 more ments

5 Answers 5

Reset to default 3

You can link index to element's property before register element in observer. Important! Your property name should be unique to avoid overwriting standard properties.

Please read ments below, i have separated the lines of code where the index has been saved (18 line) and readed (5 line).

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);
});

Open pen's console there to see result there: https://codepen.io/rafaylik/pen/jOMQQdd

You can access to the index of entry inside your forEach, no need to use indexOf().

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

The MDN web docs is well documented with nice exemples, you can most of the time find what you need there, here is the link for the forEach method

IndexOf may not work as you expect, when paring objects:

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

If IndexOf() is returnig 0 it means current entry instance is the same as the one in position 0.

Take a look at how do you create your array, maybe entries contains the same instance across the array.

you are logging the index from entries not from element array

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

this is where you get the index you actually looking for

You can check the entry target against the observed elements. So something like this:

const elementList = document.querySelectorAll('.list-of-elements')

const observer = new IntersectionObserver((entries) => {
  for(const entry of entries) {
    if (entry.isIntersecting) {
      // pare target to element list
      const currentIndex = elementList.indexOf(entry.target)
    }
  }
})

Array.from(elementList).forEach(element => observer.observe(element))

本文标签: javascriptWhy index of forEach is always 0 in array returned by IntersectionObserverStack Overflow