wiki list lazy load (intersection obs.)

This commit is contained in:
2024-04-06 15:45:39 +02:00
parent 27f02e2c2b
commit 90e78e5ac5
+50 -16
View File
@@ -45,42 +45,37 @@
<tbody> <tbody>
<tr <tr
v-for="{ vehicle, show } in computedTableData" v-for="{ vehicle, show } in computedTableData"
tabindex="0"
v-show="show" v-show="show"
tabindex="0"
:key="vehicle.type" :key="vehicle.type"
@click="previewVehicle(vehicle)" @click="previewVehicle(vehicle)"
@keydown.enter="previewVehicle(vehicle)" @keydown.enter="previewVehicle(vehicle)"
@dblclick="addVehicle(vehicle)" @dblclick="addVehicle(vehicle)"
ref="itemRefs"
> >
<td style="width: 120px"> <td style="width: 120px">
<img <img width="120" src="" :data-src="getThumbnailURL(vehicle.type, 'small')" />
width="120"
:src="getThumbnailURL(vehicle.type, 'small')"
:alt="`${vehicle.type}`"
loading="lazy"
@error="(e) => ((e.target as HTMLElement).style.display = 'none')"
/>
</td> </td>
<td :data-sponsoronly="vehicle.isSponsorsOnly"> <td :data-sponsoronly="vehicle.isSponsorsOnly">
{{ vehicle.type }} {{ vehicle.type }}
</td> </td>
<td v-if="isLocomotive(vehicle)"> <td v-if="isTractionUnit(vehicle)">
{{ $t(`wiki.${vehicle.group}`) }} {{ $t(`wiki.${vehicle.group}`) }}
</td> </td>
<td v-else>{{ $t(`wiki.${vehicle.group}`) }}</td> <td v-else>{{ $t(`wiki.${vehicle.group}`) }}</td>
<td>{{ vehicle.constructionType }}</td> <td>{{ vehicle.constructionType }}</td>
<td>{{ vehicle.length }}m</td> <td>{{ vehicle.length }}</td>
<td>{{ (vehicle.weight / 1000).toFixed(1) }}t</td> <td>{{ (vehicle.weight / 1000).toFixed(1) }}</td>
<td>{{ vehicle.maxSpeed }}km/h</td> <td>{{ vehicle.maxSpeed }}</td>
<td v-if="currentFilterMode == 'carriages'"> <td v-if="currentFilterMode == 'carriages'">
{{ !isLocomotive(vehicle) ? vehicle.cargoTypes.length : '---' }} {{ !isTractionUnit(vehicle) ? vehicle.cargoTypes.length : '---' }}
</td> </td>
<td v-if="currentFilterMode == 'tractions'"> <td v-if="currentFilterMode == 'tractions'">
{{ isLocomotive(vehicle) ? (vehicle.coldStart ? `&check;` : '&cross;') : '---' }} {{ isTractionUnit(vehicle) ? (vehicle.coldStart ? `&check;` : '&cross;') : '---' }}
</td> </td>
</tr> </tr>
</tbody> </tbody>
@@ -121,6 +116,7 @@ interface IWikiHeader {
interface IWikiRow { interface IWikiRow {
vehicle: IVehicle; vehicle: IVehicle;
show: boolean; show: boolean;
showImage: boolean;
} }
const headers: IWikiHeader[] = [ const headers: IWikiHeader[] = [
@@ -141,6 +137,7 @@ export default defineComponent({
data() { data() {
return { return {
store: useStore(), store: useStore(),
observer: null as IntersectionObserver | null,
headers, headers,
scrollTop: 0, scrollTop: 0,
@@ -156,6 +153,10 @@ export default defineComponent({
}; };
}, },
mounted() {
this.mountObserver();
},
activated() { activated() {
const tableWrapperRef = this.$refs['table-wrapper'] as HTMLElement; const tableWrapperRef = this.$refs['table-wrapper'] as HTMLElement;
@@ -165,10 +166,38 @@ export default defineComponent({
}, },
methods: { methods: {
isLocomotive: isTractionUnit, isTractionUnit,
mountObserver() {
if (this.observer) return;
this.observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.intersectionRatio > 0) {
entry.target
.querySelector('td:first-child > img')!
.setAttribute(
'src',
entry.target.querySelector('td:first-child > img')!.getAttribute('data-src')!
);
// your observer logic
console.log(entry.target.textContent, ':D');
} else {
console.log(entry.target.textContent, ':(');
}
});
});
(this.$refs['itemRefs'] as HTMLElement[]).forEach((el) => this.observer?.observe(el));
},
toggleFilter(name: typeof this.currentFilterMode) { toggleFilter(name: typeof this.currentFilterMode) {
this.currentFilterMode = this.currentFilterMode == name ? 'all' : name; this.currentFilterMode = this.currentFilterMode == name ? 'all' : name;
const tableWrapperRef = this.$refs['table-wrapper'] as HTMLElement;
tableWrapperRef.scrollTo({
top: this.scrollTop,
});
}, },
toggleSorter(header: IWikiHeader) { toggleSorter(header: IWikiHeader) {
@@ -226,6 +255,7 @@ export default defineComponent({
return this.store.vehicleDataList return this.store.vehicleDataList
.map((vehicle) => ({ .map((vehicle) => ({
vehicle, vehicle,
showImage: false,
show: show:
new RegExp(`${this.searchedVehicleTypeName.trim()}`, 'i').test(vehicle.type) && new RegExp(`${this.searchedVehicleTypeName.trim()}`, 'i').test(vehicle.type) &&
(this.currentFilterMode == 'all' || (this.currentFilterMode == 'all' ||
@@ -319,12 +349,16 @@ export default defineComponent({
td { td {
text-align: center; text-align: center;
height: 70px;
padding: 0.25em; padding: 0.25em;
height: 75px;
&[data-sponsoronly='true'] { &[data-sponsoronly='true'] {
color: salmon; color: salmon;
} }
img {
vertical-align: middle;
}
} }
} }