Мне нужно наблюдать за элементами в списке и помечать их как прочитанные, когда они появляются в окне просмотра пользователя. Но когда я добавляю новые элементы в начало массива (unshift), наблюдатель не работает :(
Я использую Vue, но знаю, что проблема не в нем.
Вот метод наблюдателя, который не срабатывает для новых элементов:
onElementObserved(entries) {
entries.forEach(({ target, isIntersecting}) => {
if (!isIntersecting) {
return;
}
this.observer.unobserve(target);
setTimeout(() => {
const i = target.getAttribute("data-index");
this.todos[i].seen = true;
}, 1000)
});
}
Элементы v-for
не имеют указанного key
, поэтому Vue отслеживает каждый элемент списка по индексу. Когда новый элемент не перемещается в список, новый элемент будет иметь индекс 0
, который уже существует в списке, поэтому существующий элемент просто вставляется на место. Поскольку новый элемент не создается, Intersection Observer не запускается.
Чтобы решить эту проблему, установите уникальный key
для каждого элемента в v-for
. Например, вы можете добавить свойство id
к каждому элементу массива, а затем связать это id
как ключ для <todo>
:
let nextId = 0;👈
const TodoList = Vue.extend({
template: `
<div>
<ul class = "TodoList">
<todo
v-for = "(todo, i) in todos"
:todo = "todo"
:observer = "observer"
:index = "i"
:key = "todo.id"👈
></todo>
</ul>
<button @click = "pushNewTodo()">PUSH NEW</button>
</div>
`,
data() {
return {
todos: [ 👇
{ id: nextId++, seen: false, text: "Add app skeleton" },
{ id: nextId++, seen: false, text: "Add to-do component" },
{ id: nextId++, seen: false, text: "Add to-do list component" },
{ id: nextId++, seen: false, text: "Style the components" },
{ id: nextId++, seen: false, text: "Add the IntersectionObserver" },
{ id: nextId++, seen: false, text: "Mark to-do's as seen" }
],
};
},
methods: {
pushNewTodo() { 👇
this.todos.unshift({ id: nextId++, seen: false, text: "Add app skeleton BLAH BLAH BLAH" })
},
}
})