還在修改程式碼,今天也會晚一點放上關鍵的程式碼。還有,明天一定放上github給連結...
把昨天的virtualized list組件加入infinite-scroller功能。
可以參考這篇文章。裡面有提到許多有關infinite-scroller的技術點
簡單來說,就是多了二個事件
<body>
<my-list id='my-list' height="500" width="120" itemSize="100 " itemCount="15">
<my-list-item><img src="https://fakeimg.pl/98x98/ff0000/?text=1" loading="lazy"></my-list-item>
<!-- 中間略過 -->
<my-list-item><img src="https://fakeimg.pl/98x98/0000ff/?text=15" loading="lazy"></my-list-item>
</my-list>
<script type="module">
import { myList, myListItem } from "./list.js";
customElements.define("my-list", myList);
customElements.define("my-list-item", myListItem);
const list = document.getElementById("my-list");
list.addEventListener("handleAddItem", (e) => {
const indexArr = e.detail.indexArr
return indexArr.forEach((index) => {
const item = document.createElement("my-list-item");
if (index % 3 === 0) {
item.innerHTML = `<img src="https://fakeimg.pl/98x98/ff0000/?text=${index + 1}" loading="lazy">`;
} else if (index % 3 === 1) {
item.innerHTML = `<img src="https://fakeimg.pl/98x98/00ff00/?text=${index + 1}" loading="lazy">`;
} else {
item.innerHTML = `<img src="https://fakeimg.pl/98x98/0000ff/?text=${index + 1}" loading="lazy">`;
}
list.appendChild(item);
})
});
list.addEventListener('addItemFinish', () => {
console.log('addItemFinish')
})
</script>
</body>
多了一個mutationObserver的變數用來存MutationObserver
mutationObserver = null
組件本體:這裡使用的Tombstones沒有太多裝飾,主要是有固定的寬和高
export class myListTombstones extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
width: 100px;
height: 100px;
background-color: #eee;
border: 1px solid #ccc;
box-sizing: border-box;
}
</style>
<div>Loading...</div>
`;
}
}
組件內使用:這裡也寫的很簡單,在列表的最後面放入tombstone,並且修改高度和增加定位點
setTombstones() {
if (!customElements.get('my-list-tombstones') ) {
customElements.define("my-list-tombstones", myListTombstones);
}
this.tombstonesNode = document.createElement('my-list-tombstones');
this.contentNode.appendChild(this.tombstonesNode);
this.tombstonesNode.style = `
position: absolute;
top: ${this.itemCount * this.itemSize}px;
left: 0;
`
this.contentNode.style.height = `${this.itemCount * this.itemSize + this.itemSize}px`;
}
使用MutationObserver,監看組件有沒有增加子組件,有的話就增加定位點,修改高度和加入indexNodeMap,最後再回傳事件
mutationCallback(mutationsList, observer) {
for (const mutation of mutationsList) {
if (mutation.type === 'childList') {
const addedNodes = mutation.addedNodes;
for (const node of addedNodes) {
node.style = `
position: absolute;
top: ${this.itemCount * this.itemSize}px;
`
this.indexNodeMap.set(this.itemCount, node);
this.itemCount = this.itemCount + 1
}
this.contentNode.style.height = `${( this.itemCount) * this.itemSize + this.itemSize}px`;
this.tombstonesNode.style.top = `${this.itemCount * this.itemSize}px`;
}
}
this.dispatchEvent(new CustomEvent('addItemFinish'))
}
setMutationObserver() {
const config = { attributes: true, childList: true, characterData: true };
this.mutationObserver = new MutationObserver(this.mutationCallback.bind(this));
this.mutationObserver.observe(this, config);
}