|
1 |
| -import { defineComponent, h } from 'vue'; |
| 1 | +import { |
| 2 | + computed, |
| 3 | + defineComponent, |
| 4 | + onMounted, |
| 5 | + onUnmounted, |
| 6 | + onUpdated, |
| 7 | + ref, |
| 8 | + Ref, |
| 9 | +} from 'vue'; |
| 10 | +// TODO: remove this |
2 | 11 | import emitter from 'tiny-emitter/instance';
|
3 | 12 | import { ItemProps, SlotProps } from './props';
|
4 | 13 |
|
5 |
| -const Wrapper = { |
6 |
| - created() { |
7 |
| - this.shapeKey = this.horizontal ? 'offsetWidth' : 'offsetHeight'; |
8 |
| - }, |
| 14 | +const useResizeChange = (props: any, rootRef: Ref<HTMLElement | null>) => { |
| 15 | + let resizeObserver: ResizeObserver | null = null; |
| 16 | + const shapeKey = computed(() => |
| 17 | + props.horizontal ? 'offsetWidth' : 'offsetHeight', |
| 18 | + ); |
| 19 | + |
| 20 | + const getCurrentSize = () => { |
| 21 | + return rootRef.value ? rootRef.value[shapeKey.value] : 0; |
| 22 | + }; |
9 | 23 |
|
10 |
| - mounted() { |
| 24 | + // tell parent current size identify by unqiue key |
| 25 | + const dispatchSizeChange = () => { |
| 26 | + const { event, uniqueKey, hasInitial } = props; |
| 27 | + console.log(getCurrentSize()); |
| 28 | + emitter.emit(event, uniqueKey, getCurrentSize(), hasInitial); |
| 29 | + }; |
| 30 | + |
| 31 | + onMounted(() => { |
11 | 32 | if (typeof ResizeObserver !== 'undefined') {
|
12 |
| - this.resizeObserver = new ResizeObserver(() => { |
13 |
| - this.dispatchSizeChange(); |
| 33 | + resizeObserver = new ResizeObserver(() => { |
| 34 | + dispatchSizeChange(); |
14 | 35 | });
|
15 |
| - this.resizeObserver.observe(this.$el); |
| 36 | + rootRef.value && resizeObserver.observe(rootRef.value); |
16 | 37 | }
|
17 |
| - }, |
| 38 | + }); |
18 | 39 |
|
19 |
| - // since componet will be reused, so disptach when updated |
20 |
| - updated() { |
21 |
| - this.dispatchSizeChange(); |
22 |
| - }, |
| 40 | + onUpdated(() => { |
| 41 | + dispatchSizeChange(); |
| 42 | + }); |
23 | 43 |
|
24 |
| - beforeDestroy() { |
25 |
| - if (this.resizeObserver) { |
26 |
| - this.resizeObserver.disconnect(); |
27 |
| - this.resizeObserver = null; |
| 44 | + onUnmounted(() => { |
| 45 | + if (resizeObserver) { |
| 46 | + resizeObserver.disconnect(); |
| 47 | + resizeObserver = null; |
28 | 48 | }
|
29 |
| - }, |
30 |
| - |
31 |
| - methods: { |
32 |
| - getCurrentSize() { |
33 |
| - return this.$el ? this.$el[this.shapeKey] : 0; |
34 |
| - }, |
35 |
| - |
36 |
| - // tell parent current size identify by unqiue key |
37 |
| - dispatchSizeChange() { |
38 |
| - emitter.emit( |
39 |
| - this.event, |
40 |
| - this.uniqueKey, |
41 |
| - this.getCurrentSize(), |
42 |
| - this.hasInitial, |
43 |
| - ); |
44 |
| - // this.$parent.$emit(this.event, this.uniqueKey, this.getCurrentSize(), this.hasInitial) |
45 |
| - }, |
46 |
| - }, |
| 49 | + }); |
47 | 50 | };
|
48 | 51 |
|
49 | 52 | export const Item = defineComponent({
|
50 | 53 | name: 'VirtualListItem',
|
51 |
| - mixins: [Wrapper], |
52 | 54 | props: ItemProps,
|
53 |
| - render() { |
54 |
| - const { |
55 |
| - tag, |
56 |
| - component, |
57 |
| - extraProps = {}, |
58 |
| - index, |
59 |
| - source, |
60 |
| - scopedSlots = {}, |
61 |
| - uniqueKey, |
62 |
| - } = this; |
63 |
| - const props = { |
64 |
| - ...extraProps, |
65 |
| - source, |
66 |
| - index, |
67 |
| - }; |
| 55 | + setup(props) { |
| 56 | + const rootRef = ref<HTMLElement | null>(null); |
| 57 | + useResizeChange(props, rootRef); |
| 58 | + |
| 59 | + return () => { |
| 60 | + const { |
| 61 | + tag: Tag, |
| 62 | + component: Comp, |
| 63 | + extraProps = {}, |
| 64 | + index, |
| 65 | + source, |
| 66 | + scopedSlots = {}, |
| 67 | + uniqueKey, |
| 68 | + } = props; |
| 69 | + const mergedProps = { |
| 70 | + ...extraProps, |
| 71 | + source, |
| 72 | + index, |
| 73 | + }; |
68 | 74 |
|
69 |
| - return h( |
70 |
| - tag, |
71 |
| - { |
72 |
| - key: uniqueKey, |
73 |
| - }, |
74 |
| - [ |
75 |
| - h(component, { |
76 |
| - ...props, |
77 |
| - scopedSlots: scopedSlots, |
78 |
| - }), |
79 |
| - ], |
80 |
| - ); |
| 75 | + return ( |
| 76 | + <Tag key={uniqueKey} ref={rootRef}> |
| 77 | + <Comp {...mergedProps} scopedSlots={scopedSlots} /> |
| 78 | + </Tag> |
| 79 | + ); |
| 80 | + }; |
81 | 81 | },
|
82 | 82 | });
|
83 | 83 |
|
84 | 84 | export const Slot = defineComponent({
|
85 |
| - mixins: [Wrapper], |
| 85 | + name: 'VirtualListSlot', |
86 | 86 | props: SlotProps,
|
87 | 87 | setup(props, { slots }) {
|
| 88 | + const rootRef = ref<HTMLElement | null>(null); |
| 89 | + useResizeChange(props, rootRef); |
| 90 | + |
88 | 91 | return () => {
|
89 |
| - const { tag, uniqueKey } = props; |
| 92 | + const { tag: Tag, uniqueKey } = props; |
90 | 93 |
|
91 |
| - return h( |
92 |
| - tag, |
93 |
| - { |
94 |
| - key: uniqueKey, |
95 |
| - }, |
96 |
| - slots.default(), |
| 94 | + return ( |
| 95 | + <Tag ref={rootRef} key={uniqueKey}> |
| 96 | + {slots.default?.()} |
| 97 | + </Tag> |
97 | 98 | );
|
98 | 99 | };
|
99 | 100 | },
|
|
0 commit comments