- У меня зарегистрирован наблюдатель мутации в родительском div с divами в качестве дочерних элементов
- Я показываю только подмножество дочерних элементов на основе startIndex и endIndex
- Когда я увеличиваю startIndex, элементы удалены, и я хочу, чтобы их высота переводилась соответствующим образом
- Я получаю их scrollHeight как всегда 0
- Как мне получить их высоту, как это было до того, как они были удалены
HTML
<script type="text/x-template" id="virtual-list">
<div id="root" ref="root">
<div id="viewport" ref="viewport">
<div id="spacer" ref="spacer" :style="spacerStyle">
<div v-for="i in visibleItems" :key="i.index" :id="i.index" class="list-item">
{{i.value}}
</div>
</div>
</div>
</div>
</script>
<div id="app">
<button @click="incrementStart">Start +</button>
<button @click="decrementStart">Start -</button>
<button @click="incrementEnd">End +</button>
<button @click="decrementEnd">End -</button>
<virtual-list></virtual-list>
</div>
CSS
* {
box-sizing: border-box;
}
html,
body,
#app {
height: 100%;
}
#app {
padding: 1.25rem;
}
#root {
height: 50%;
overflow-y: auto;
}
.list-item {
padding: 0.75rem 0;
}
JS
const PAGE_SIZE = 50;
const items = new Array(PAGE_SIZE).fill(null).map((item, index) => {
return {
id: faker.random.uuid(),
index: index,
value: "Item " + index + " " + faker.random.words(index % 25)
};
});
const bus = new Vue({});
Vue.component("virtual-list", {
template: "#virtual-list",
data() {
return {
isMounted: false,
items,
startIndex: 0,
endIndex: PAGE_SIZE,
scrollTop: 0,
translateY: 0,
observer: null
};
},
computed: {
visibleItems() {
return this.items.slice(this.startIndex, this.endIndex);
},
/**
Translate the spacer verticaly to keep the scrollbar intact
We only show N items at a time so the scrollbar would get affected if we dont translate
*/
spacerStyle() {
return {
willChange: "auto",
transform: "translateY(" + this.translateY + "px)"
};
}
},
methods: {
onMutation(entries) {
for (const entry of entries) {
if (entry.type === "childList") {
this.$nextTick(() => {
if (entry.removedNodes && entry.removedNodes.length) {
for (let i of entry.removedNodes) {
console.log(
entry.removedNodes.length,
"removed",
i.scrollHeight,
i.offsetHeight,
i.clientHeight,
i.getAttribute("data-height"),
i
);
this.translateY += 42;
}
}
});
if (entry.addedNodes && entry.addedNodes.length) {
for (let i of entry.addedNodes) {
console.log(
entry.addedNodes.length,
"added",
i.scrollHeight,
i.offsetHeight,
i.clientHeight,
i.getAttribute("data-height")
);
this.translateY -= 42;
}
}
}
}
},
handleScroll() {
this.scrollTop = this.$el.scrollTop;
this.startIndex = Math.floor(this.scrollTop / 42);
// this.endIndex = Math.ceil((this.scrollTop + this.$el.offsetHeight) / 42)
// console.log(this.scrollTop, Math.floor(this.scrollTop / 42), Math.ceil((this.scrollTop + this.$el.offsetHeight) / 42));
}
},
watch: {
scrollTop(newValue, oldValue) {},
startIndex(newValue, oldValue) {
// console.log(this.$refs.spacer.children);
}
},
beforeUpdate() {
// console.log('before update', this.$refs.spacer.children);
},
mounted() {
this.isMounted = true;
const children = this.$refs.spacer.children;
for (let i = 0; i < children.length; i++) {
// console.log(children[i].offsetTop - this.$el.offsetTop);
children[i].setAttribute("data-height", children[i].scrollHeight);
}
bus.$on("incrementStart", () => {
this.startIndex++;
});
bus.$on("decrementStart", () => {
this.startIndex--;
});
bus.$on("incrementEnd", () => {
this.endIndex++;
});
bus.$on("decrementEnd", () => {
this.endIndex--;
});
this.observer = new MutationObserver(this.onMutation);
this.observer.observe(this.$refs.spacer, {
childList: true,
attributes: true
});
this.$el.addEventListener("scroll", this.handleScroll);
},
destroyed() {
this.observer && this.observer.disconnect();
this.$el.removeEventListener("scroll", this.handleScroll);
}
});
new Vue({
el: "#app",
methods: {
incrementStart() {
bus.$emit("incrementStart");
},
decrementStart() {
bus.$emit("decrementStart");
},
incrementEnd() {
bus.$emit("incrementEnd");
},
decrementEnd() {
bus.$emit("decrementEnd");
}
}
});
- В приведенном выше методе onMutation вы можете видеть, что scrollHeight для удаленных узлов, offsetHeight, clientHeight et c всегда равен 0, как получить их значения?