feat: 初始化
This commit is contained in:
140
pages/components/baseTree/list.vue
Normal file
140
pages/components/baseTree/list.vue
Normal file
@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<view class="VirtualizationList virtualization-list" @scroll.passive="update" >
|
||||
<component
|
||||
:is="listTag"
|
||||
:class="listClass"
|
||||
>
|
||||
<template v-for="(info, i) in visibleItems" :key="info.item.$id">
|
||||
<slot
|
||||
:item="info.item"
|
||||
:index="info.index"
|
||||
:renderIndex="i"
|
||||
:itemStyle="{ marginBottom: gap + 'px' }"
|
||||
{{ info.item.text }}
|
||||
></slot>
|
||||
</template>
|
||||
</component>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, nextTick } from "./vue"
|
||||
import { obj } from "./types"
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
items: { type: Array as PropType<obj[]>, default: () => [] },
|
||||
enabled: { type: Boolean, default: true },
|
||||
buffer: {
|
||||
type: Number,
|
||||
default: 200,
|
||||
},
|
||||
minItemHeight: { type: Number, default: 20 },
|
||||
prerender: { type: Number, default: 20 },
|
||||
listTag: { type: String, default: "view" },
|
||||
listClass: { type: String },
|
||||
itemClass: { type: String, default: "vl-item" },
|
||||
gap: { type: Number, default: 0 },
|
||||
afterCalcTop2: { type: Function as PropType<(top2: number) => number> },
|
||||
isForceVisible: {
|
||||
type: Function as PropType<(node: obj, index: number) => boolean>,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
start: 0,
|
||||
end: -1,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
totalHeight: 0,
|
||||
itemsHeight: <number[]>[],
|
||||
mountedPromise: new Promise((resolve, reject) => {
|
||||
this._mountedPromise_resolve = resolve;
|
||||
}),
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
visibleItems(): { item: obj; index: number }[] {
|
||||
const r: { item: obj; index: number }[] = [];
|
||||
console.log(this.items)
|
||||
this.items.forEach((item: obj, index: number) => {
|
||||
if (!this.enabled) {
|
||||
r.push({ item, index });
|
||||
} else if (
|
||||
(index >= this.start && index <= this.end) ||
|
||||
(this.isForceVisible && this.isForceVisible(item, index))
|
||||
) {
|
||||
r.push({ item, index });
|
||||
}
|
||||
});
|
||||
console.log(r)
|
||||
return r;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
enabled: {
|
||||
immediate: true,
|
||||
handler() {
|
||||
if (!this.enabled) {
|
||||
// @ts-ignore
|
||||
this.totalHeight = undefined;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getItemElHeight(el: UniApp.NodesRef) {
|
||||
return new Promise((resolve, reject) => {
|
||||
el.boundingClientRect(res => {
|
||||
if(res) {
|
||||
resolve(res)
|
||||
} else {
|
||||
reject(res)
|
||||
}
|
||||
}).exec()
|
||||
})
|
||||
},
|
||||
update() {
|
||||
const task = async () => {
|
||||
this.start = 0;
|
||||
this.end = this.items.length;
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.bottom = this.prerender - 1;
|
||||
},
|
||||
mounted() {
|
||||
// @ts-ignore
|
||||
this._mountedPromise_resolve!(null);
|
||||
let updatedOnce = false;
|
||||
this.$watch(
|
||||
() => [this.items],
|
||||
() => {
|
||||
this.itemsHeight = [];
|
||||
nextTick(() => {
|
||||
this.update();
|
||||
if (!updatedOnce) {
|
||||
this.update();
|
||||
}
|
||||
updatedOnce = true;
|
||||
});
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
this.$watch(
|
||||
() => [this.buffer],
|
||||
() => {
|
||||
this.update();
|
||||
}
|
||||
);
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.vl-items {
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user