Skip to content
This repository was archived by the owner on Nov 5, 2023. It is now read-only.

Commit 93c85c1

Browse files
committed
refactor: the vue component
1 parent 1ea462d commit 93c85c1

File tree

3 files changed

+62
-69
lines changed

3 files changed

+62
-69
lines changed

src/Grid.vue

Lines changed: 23 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,10 @@
4040
</template>
4141

4242
<script lang="ts">
43-
import { defineComponent, onMounted, PropType, ref } from "vue";
44-
import { fromEvent, fromEventPattern, Observable } from "rxjs";
45-
import { pluck, share, switchMapTo } from "rxjs/operators";
43+
import { defineComponent, PropType, ref } from "vue";
4644
import { useObservable } from "@vueuse/rxjs";
47-
import { fromProp, fromResizeObserver } from "./utilites";
48-
import { InternalItem, PageProvider, pipeline } from "./pipeline";
45+
import { fromProp, fromResizeObserver, fromWindowScroll } from "./utilites";
46+
import { PageProvider, pipeline } from "./pipeline";
4947
5048
export default defineComponent({
5149
name: "Grid",
@@ -69,62 +67,33 @@ export default defineComponent({
6967
},
7068
},
7169
setup(props) {
72-
// region: props
73-
const length$ = fromProp(props, "length");
74-
const pageSize$ = fromProp(props, "pageSize");
75-
const pageProvider$ = fromProp(props, "pageProvider");
76-
// endregion
77-
78-
// region: refs
70+
// template refs
7971
const rootRef = ref<Element>(document.createElement("div"));
8072
const probeRef = ref<Element>(document.createElement("div"));
81-
// endregion
82-
83-
// region: rendering triggers
84-
// a stream of root elements when scrolling
85-
// @ts-expect-error Rxjs has a typing bug on fromEvent() with resultSelector
86-
// which is fixed in https://github.com/ReactiveX/rxjs/pull/6447
87-
const scroll$: Observable<Element> = fromEventPattern(onMounted).pipe(
88-
// use share() to push the "mounted" event from vue, instead of pulling:
89-
share(),
90-
switchMapTo(
91-
fromEvent<UIEvent, Element>(
92-
window,
93-
"scroll",
94-
{ passive: true, capture: true },
95-
() => rootRef.value
96-
)
97-
)
98-
);
99-
100-
// a stream of root elements when it is resized
101-
const rootResize$: Observable<Element> = fromResizeObserver(rootRef).pipe(
102-
pluck("target")
103-
);
104-
105-
// a stream of item size measurements when it is changed
106-
const itemRect$: Observable<DOMRectReadOnly> = fromResizeObserver(
107-
probeRef
108-
).pipe(pluck("contentRect"));
109-
// endregion
11073
111-
// region: data to render
74+
// data to render
11275
const {
11376
buffer$, // the items in the current scanning window
11477
contentHeight$, // the height of the whole list
115-
} = pipeline(
116-
itemRect$,
117-
length$,
118-
pageProvider$,
119-
pageSize$,
120-
rootResize$,
121-
scroll$
122-
);
123-
const buffer = useObservable<InternalItem[]>(buffer$);
124-
const contentHeight = useObservable<number>(contentHeight$);
125-
// endregion
78+
} = pipeline({
79+
// streams of prop
80+
length$: fromProp(props, "length"),
81+
pageProvider$: fromProp(props, "pageProvider"),
82+
pageSize$: fromProp(props, "pageSize"),
83+
// a stream of item size measurements when it is changed
84+
itemRect$: fromResizeObserver(probeRef, "contentRect"),
85+
// a stream of root elements when it is resized
86+
rootResize$: fromResizeObserver(rootRef, "target"),
87+
// a stream of root elements when scrolling
88+
scroll$: fromWindowScroll(() => rootRef.value),
89+
});
12690
127-
return { rootRef, probeRef, buffer, contentHeight };
91+
return {
92+
rootRef,
93+
probeRef,
94+
buffer: useObservable(buffer$),
95+
contentHeight: useObservable(contentHeight$),
96+
};
12897
},
12998
});
13099
</script>

src/pipeline.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -214,19 +214,28 @@ export function getContentHeight(
214214
return itemHeightWithGap * Math.ceil(length / columns) - rowGap;
215215
}
216216

217+
interface PipelineInput {
218+
length$: Observable<number>;
219+
pageProvider$: Observable<PageProvider>;
220+
pageSize$: Observable<number>;
221+
itemRect$: Observable<DOMRectReadOnly>;
222+
rootResize$: Observable<Element>;
223+
scroll$: Observable<Element>;
224+
}
225+
217226
interface PipelineOutput {
218227
buffer$: Observable<InternalItem[]>;
219228
contentHeight$: Observable<number>;
220229
}
221230

222-
export function pipeline(
223-
itemRect$: Observable<DOMRectReadOnly>,
224-
length$: Observable<number>,
225-
pageProvider$: Observable<PageProvider>,
226-
pageSize$: Observable<number>,
227-
rootResize$: Observable<Element>,
228-
scroll$: Observable<Element>
229-
): PipelineOutput {
231+
export function pipeline({
232+
length$,
233+
pageProvider$,
234+
pageSize$,
235+
itemRect$,
236+
rootResize$,
237+
scroll$,
238+
}: PipelineInput): PipelineOutput {
230239
// region: measurements of the visual grid
231240
const heightAboveWindow$: Observable<number> = merge(
232241
rootResize$,

src/utilites.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { fromEventPattern, Observable } from "rxjs";
1+
import { fromEvent, fromEventPattern, Observable } from "rxjs";
22
import { Ref, watchEffect } from "vue";
33
import { partial, pipe, unary } from "ramda";
4-
import { useResizeObserver } from "@vueuse/core";
5-
import { mergeAll } from "rxjs/operators";
4+
import { ResizeObserverEntry, useResizeObserver } from "@vueuse/core";
5+
import { mergeAll, pluck } from "rxjs/operators";
66

77
export function fromProp<T, U extends keyof T>(
88
props: T,
@@ -13,10 +13,25 @@ export function fromProp<T, U extends keyof T>(
1313
);
1414
}
1515

16-
export function fromResizeObserver(
17-
elRef: Ref<Element>
18-
): Observable<ResizeObserverEntry> {
16+
export function fromResizeObserver<T extends keyof ResizeObserverEntry>(
17+
elRef: Ref<Element>,
18+
pluckTarget: T
19+
): Observable<ResizeObserverEntry[T]> {
1920
return fromEventPattern<ResizeObserverEntry[]>(
2021
pipe(unary, partial(useResizeObserver, [elRef]))
21-
).pipe(mergeAll());
22+
).pipe(mergeAll(), pluck<ResizeObserverEntry, T>(pluckTarget));
23+
}
24+
25+
export function fromWindowScroll<T>(
26+
resultSelector: (e: Event) => T
27+
): Observable<T> {
28+
// @ts-expect-error Rxjs has a typing bug on fromEvent() with resultSelector,
29+
// which is fixed in https://github.com/ReactiveX/rxjs/pull/6447.
30+
// TODO: Remove this comment when the PR above is merged.
31+
return fromEvent(
32+
window,
33+
"scroll",
34+
{ passive: true, capture: true },
35+
resultSelector
36+
);
2237
}

0 commit comments

Comments
 (0)