Commit 6a9bd686d5e7d3928f39856da4e9e3920ac5cbee
1 parent
6890dd72
chore: remove LazyContainer
Showing
11 changed files
with
2 additions
and
382 deletions
packages/hooks/src/useRefs.ts
1 | import type { Ref } from 'vue'; | 1 | import type { Ref } from 'vue'; |
2 | -import { onBeforeUpdate, ref } from 'vue'; | 2 | +import { onBeforeUpdate, shallowRef } from 'vue'; |
3 | 3 | ||
4 | export function useRefs(): [Ref<HTMLElement[]>, (index: number) => (el: HTMLElement) => void] { | 4 | export function useRefs(): [Ref<HTMLElement[]>, (index: number) => (el: HTMLElement) => void] { |
5 | - const refs = ref([]) as Ref<HTMLElement[]>; | 5 | + const refs = shallowRef([]) as Ref<HTMLElement[]>; |
6 | 6 | ||
7 | onBeforeUpdate(() => { | 7 | onBeforeUpdate(() => { |
8 | refs.value = []; | 8 | refs.value = []; |
src/components/Container/index.ts
1 | import { withInstall } from '/@/utils'; | 1 | import { withInstall } from '/@/utils'; |
2 | import collapseContainer from './src/collapse/CollapseContainer.vue'; | 2 | import collapseContainer from './src/collapse/CollapseContainer.vue'; |
3 | import scrollContainer from './src/ScrollContainer.vue'; | 3 | import scrollContainer from './src/ScrollContainer.vue'; |
4 | -import lazyContainer from './src/LazyContainer.vue'; | ||
5 | 4 | ||
6 | export const CollapseContainer = withInstall(collapseContainer); | 5 | export const CollapseContainer = withInstall(collapseContainer); |
7 | export const ScrollContainer = withInstall(scrollContainer); | 6 | export const ScrollContainer = withInstall(scrollContainer); |
8 | -export const LazyContainer = withInstall(lazyContainer); | ||
9 | 7 | ||
10 | export * from './src/typing'; | 8 | export * from './src/typing'; |
src/components/Container/src/LazyContainer.vue deleted
100644 → 0
1 | -<template> | ||
2 | - <transition-group | ||
3 | - class="h-full w-full" | ||
4 | - v-bind="$attrs" | ||
5 | - ref="elRef" | ||
6 | - :name="transitionName" | ||
7 | - :tag="tag" | ||
8 | - mode="out-in" | ||
9 | - > | ||
10 | - <div key="component" v-if="isInit"> | ||
11 | - <slot :loading="loading"></slot> | ||
12 | - </div> | ||
13 | - <div key="skeleton" v-else> | ||
14 | - <slot name="skeleton" v-if="$slots.skeleton"></slot> | ||
15 | - <Skeleton v-else /> | ||
16 | - </div> | ||
17 | - </transition-group> | ||
18 | -</template> | ||
19 | -<script lang="ts"> | ||
20 | - import type { PropType } from 'vue'; | ||
21 | - import { defineComponent, reactive, onMounted, ref, toRef, toRefs } from 'vue'; | ||
22 | - import { useTimeoutFn } from '@vben/hooks'; | ||
23 | - import { Skeleton } from 'ant-design-vue'; | ||
24 | - import { useIntersectionObserver } from '/@/hooks/event/useIntersectionObserver'; | ||
25 | - | ||
26 | - interface State { | ||
27 | - isInit: boolean; | ||
28 | - loading: boolean; | ||
29 | - intersectionObserverInstance: IntersectionObserver | null; | ||
30 | - } | ||
31 | - | ||
32 | - const props = { | ||
33 | - /** | ||
34 | - * Waiting time, if the time is specified, whether visible or not, it will be automatically loaded after the specified time | ||
35 | - */ | ||
36 | - timeout: { type: Number }, | ||
37 | - /** | ||
38 | - * The viewport where the component is located. | ||
39 | - * If the component is scrolling in the page container, the viewport is the container | ||
40 | - */ | ||
41 | - viewport: { | ||
42 | - type: (typeof window !== 'undefined' ? window.HTMLElement : Object) as PropType<HTMLElement>, | ||
43 | - default: () => null, | ||
44 | - }, | ||
45 | - /** | ||
46 | - * Preload threshold, css unit | ||
47 | - */ | ||
48 | - threshold: { type: String, default: '0px' }, | ||
49 | - /** | ||
50 | - * The scroll direction of the viewport, vertical represents the vertical direction, horizontal represents the horizontal direction | ||
51 | - */ | ||
52 | - direction: { | ||
53 | - type: String, | ||
54 | - default: 'vertical', | ||
55 | - validator: (v) => ['vertical', 'horizontal'].includes(v), | ||
56 | - }, | ||
57 | - /** | ||
58 | - * The label name of the outer container that wraps the component | ||
59 | - */ | ||
60 | - tag: { type: String, default: 'div' }, | ||
61 | - maxWaitingTime: { type: Number, default: 80 }, | ||
62 | - /** | ||
63 | - * transition name | ||
64 | - */ | ||
65 | - transitionName: { type: String, default: 'lazy-container' }, | ||
66 | - }; | ||
67 | - | ||
68 | - export default defineComponent({ | ||
69 | - name: 'LazyContainer', | ||
70 | - components: { Skeleton }, | ||
71 | - inheritAttrs: false, | ||
72 | - props, | ||
73 | - emits: ['init'], | ||
74 | - setup(props, { emit }) { | ||
75 | - const elRef = ref(); | ||
76 | - const state = reactive<State>({ | ||
77 | - isInit: false, | ||
78 | - loading: false, | ||
79 | - intersectionObserverInstance: null, | ||
80 | - }); | ||
81 | - | ||
82 | - onMounted(() => { | ||
83 | - immediateInit(); | ||
84 | - initIntersectionObserver(); | ||
85 | - }); | ||
86 | - | ||
87 | - // If there is a set delay time, it will be executed immediately | ||
88 | - function immediateInit() { | ||
89 | - const { timeout } = props; | ||
90 | - timeout && | ||
91 | - useTimeoutFn(() => { | ||
92 | - init(); | ||
93 | - }, timeout); | ||
94 | - } | ||
95 | - | ||
96 | - function init() { | ||
97 | - state.loading = true; | ||
98 | - | ||
99 | - useTimeoutFn(() => { | ||
100 | - if (state.isInit) return; | ||
101 | - state.isInit = true; | ||
102 | - emit('init'); | ||
103 | - }, props.maxWaitingTime || 80); | ||
104 | - } | ||
105 | - | ||
106 | - function initIntersectionObserver() { | ||
107 | - const { timeout, direction, threshold } = props; | ||
108 | - if (timeout) return; | ||
109 | - // According to the scrolling direction to construct the viewport margin, used to load in advance | ||
110 | - let rootMargin = '0px'; | ||
111 | - switch (direction) { | ||
112 | - case 'vertical': | ||
113 | - rootMargin = `${threshold} 0px`; | ||
114 | - break; | ||
115 | - case 'horizontal': | ||
116 | - rootMargin = `0px ${threshold}`; | ||
117 | - break; | ||
118 | - } | ||
119 | - | ||
120 | - try { | ||
121 | - const { stop, observer } = useIntersectionObserver({ | ||
122 | - rootMargin, | ||
123 | - target: toRef(elRef.value, '$el'), | ||
124 | - onIntersect: (entries: any[]) => { | ||
125 | - const isIntersecting = entries[0].isIntersecting || entries[0].intersectionRatio; | ||
126 | - if (isIntersecting) { | ||
127 | - init(); | ||
128 | - if (observer) { | ||
129 | - stop(); | ||
130 | - } | ||
131 | - } | ||
132 | - }, | ||
133 | - root: toRef(props, 'viewport'), | ||
134 | - }); | ||
135 | - } catch (e) { | ||
136 | - init(); | ||
137 | - } | ||
138 | - } | ||
139 | - return { | ||
140 | - elRef, | ||
141 | - ...toRefs(state), | ||
142 | - }; | ||
143 | - }, | ||
144 | - }); | ||
145 | -</script> |
src/hooks/event/useIntersectionObserver.ts deleted
100644 → 0
1 | -import { Ref, watchEffect, ref } from 'vue'; | ||
2 | - | ||
3 | -interface IntersectionObserverProps { | ||
4 | - target: Ref<Element | null | undefined>; | ||
5 | - root?: Ref<any>; | ||
6 | - onIntersect: IntersectionObserverCallback; | ||
7 | - rootMargin?: string; | ||
8 | - threshold?: number; | ||
9 | -} | ||
10 | - | ||
11 | -export function useIntersectionObserver({ | ||
12 | - target, | ||
13 | - root, | ||
14 | - onIntersect, | ||
15 | - rootMargin = '0px', | ||
16 | - threshold = 0.1, | ||
17 | -}: IntersectionObserverProps) { | ||
18 | - let cleanup = () => {}; | ||
19 | - const observer: Ref<Nullable<IntersectionObserver>> = ref(null); | ||
20 | - const stopEffect = watchEffect(() => { | ||
21 | - cleanup(); | ||
22 | - | ||
23 | - observer.value = new IntersectionObserver(onIntersect, { | ||
24 | - root: root ? root.value : null, | ||
25 | - rootMargin, | ||
26 | - threshold, | ||
27 | - }); | ||
28 | - | ||
29 | - const current = target.value; | ||
30 | - | ||
31 | - current && observer.value.observe(current); | ||
32 | - | ||
33 | - cleanup = () => { | ||
34 | - if (observer.value) { | ||
35 | - observer.value.disconnect(); | ||
36 | - target.value && observer.value.unobserve(target.value); | ||
37 | - } | ||
38 | - }; | ||
39 | - }); | ||
40 | - | ||
41 | - return { | ||
42 | - observer, | ||
43 | - stop: () => { | ||
44 | - cleanup(); | ||
45 | - stopEffect(); | ||
46 | - }, | ||
47 | - }; | ||
48 | -} |
src/hooks/web/useMessage.tsx
1 | import type { ModalFunc, ModalFuncProps } from 'ant-design-vue/lib/modal/Modal'; | 1 | import type { ModalFunc, ModalFuncProps } from 'ant-design-vue/lib/modal/Modal'; |
2 | - | ||
3 | import { Modal, message as Message, notification } from 'ant-design-vue'; | 2 | import { Modal, message as Message, notification } from 'ant-design-vue'; |
4 | import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue'; | 3 | import { InfoCircleFilled, CheckCircleFilled, CloseCircleFilled } from '@ant-design/icons-vue'; |
5 | - | ||
6 | import { NotificationArgsProps, ConfigProps } from 'ant-design-vue/lib/notification'; | 4 | import { NotificationArgsProps, ConfigProps } from 'ant-design-vue/lib/notification'; |
7 | import { useI18n } from './useI18n'; | 5 | import { useI18n } from './useI18n'; |
8 | import { isString } from '/@/utils/is'; | 6 | import { isString } from '/@/utils/is'; |
src/locales/lang/en/routes/demo.ts
@@ -29,10 +29,6 @@ export default { | @@ -29,10 +29,6 @@ export default { | ||
29 | drawer: 'Drawer', | 29 | drawer: 'Drawer', |
30 | desc: 'Desc', | 30 | desc: 'Desc', |
31 | 31 | ||
32 | - lazy: 'Lazy', | ||
33 | - lazyBasic: 'Basic', | ||
34 | - lazyTransition: 'Animation', | ||
35 | - | ||
36 | verify: 'Verify', | 32 | verify: 'Verify', |
37 | verifyDrag: 'Drag ', | 33 | verifyDrag: 'Drag ', |
38 | verifyRotate: 'Picture Restore', | 34 | verifyRotate: 'Picture Restore', |
src/locales/lang/zh-CN/routes/demo.ts
@@ -28,10 +28,6 @@ export default { | @@ -28,10 +28,6 @@ export default { | ||
28 | drawer: '抽屉扩展', | 28 | drawer: '抽屉扩展', |
29 | desc: '详情组件', | 29 | desc: '详情组件', |
30 | 30 | ||
31 | - lazy: '懒加载组件', | ||
32 | - lazyBasic: '基础示例', | ||
33 | - lazyTransition: '动画效果', | ||
34 | - | ||
35 | verify: '验证组件', | 31 | verify: '验证组件', |
36 | verifyDrag: '拖拽校验', | 32 | verifyDrag: '拖拽校验', |
37 | verifyRotate: '图片还原', | 33 | verifyRotate: '图片还原', |
src/router/routes/modules/demo/comp.ts
@@ -471,33 +471,6 @@ const comp: AppRouteModule = { | @@ -471,33 +471,6 @@ const comp: AppRouteModule = { | ||
471 | }, | 471 | }, |
472 | 472 | ||
473 | { | 473 | { |
474 | - path: 'lazy', | ||
475 | - name: 'LazyDemo', | ||
476 | - component: getParentLayout('LazyDemo'), | ||
477 | - redirect: '/comp/lazy/basic', | ||
478 | - meta: { | ||
479 | - title: t('routes.demo.comp.lazy'), | ||
480 | - }, | ||
481 | - children: [ | ||
482 | - { | ||
483 | - path: 'basic', | ||
484 | - name: 'BasicLazyDemo', | ||
485 | - component: () => import('/@/views/demo/comp/lazy/index.vue'), | ||
486 | - meta: { | ||
487 | - title: t('routes.demo.comp.lazyBasic'), | ||
488 | - }, | ||
489 | - }, | ||
490 | - { | ||
491 | - path: 'transition', | ||
492 | - name: 'BasicTransitionDemo', | ||
493 | - component: () => import('/@/views/demo/comp/lazy/Transition.vue'), | ||
494 | - meta: { | ||
495 | - title: t('routes.demo.comp.lazyTransition'), | ||
496 | - }, | ||
497 | - }, | ||
498 | - ], | ||
499 | - }, | ||
500 | - { | ||
501 | path: 'verify', | 474 | path: 'verify', |
502 | name: 'VerifyDemo', | 475 | name: 'VerifyDemo', |
503 | component: getParentLayout('VerifyDemo'), | 476 | component: getParentLayout('VerifyDemo'), |
src/views/demo/comp/lazy/TargetContent.vue deleted
100644 → 0
1 | -<template> | ||
2 | - <Card hoverable :style="{ width: '240px', background: '#fff' }"> | ||
3 | - <template #cover> | ||
4 | - <img alt="example" src="https://os.alipayobjects.com/rmsportal/QBnOOoLaAfKPirc.png" /> | ||
5 | - </template> | ||
6 | - <CardMeta title="懒加载组件" /> | ||
7 | - </Card> | ||
8 | -</template> | ||
9 | -<script lang="ts"> | ||
10 | - import { defineComponent } from 'vue'; | ||
11 | - import { Card } from 'ant-design-vue'; | ||
12 | - | ||
13 | - export default defineComponent({ | ||
14 | - components: { CardMeta: Card.Meta, Card }, | ||
15 | - setup() { | ||
16 | - return {}; | ||
17 | - }, | ||
18 | - }); | ||
19 | -</script> |
src/views/demo/comp/lazy/Transition.vue deleted
100644 → 0
1 | -<template> | ||
2 | - <PageWrapper title="懒加载自定义动画示例" content="懒加载组件显示动画"> | ||
3 | - <div class="lazy-base-demo-wrap"> | ||
4 | - <h1>向下滚动</h1> | ||
5 | - | ||
6 | - <div class="lazy-base-demo-box"> | ||
7 | - <LazyContainer transitionName="custom"> | ||
8 | - <TargetContent /> | ||
9 | - </LazyContainer> | ||
10 | - </div> | ||
11 | - </div> | ||
12 | - </PageWrapper> | ||
13 | -</template> | ||
14 | -<script lang="ts"> | ||
15 | - import { defineComponent } from 'vue'; | ||
16 | - import TargetContent from './TargetContent.vue'; | ||
17 | - import { LazyContainer } from '/@/components/Container/index'; | ||
18 | - import { PageWrapper } from '/@/components/Page'; | ||
19 | - | ||
20 | - export default defineComponent({ | ||
21 | - components: { LazyContainer, TargetContent, PageWrapper }, | ||
22 | - }); | ||
23 | -</script> | ||
24 | -<style lang="less"> | ||
25 | - .lazy-base-demo { | ||
26 | - &-wrap { | ||
27 | - display: flex; | ||
28 | - flex-direction: column; | ||
29 | - align-items: center; | ||
30 | - justify-content: center; | ||
31 | - width: 50%; | ||
32 | - height: 2000px; | ||
33 | - margin: 20px auto; | ||
34 | - background-color: @component-background; | ||
35 | - text-align: center; | ||
36 | - } | ||
37 | - | ||
38 | - &-box { | ||
39 | - width: 300px; | ||
40 | - height: 300px; | ||
41 | - } | ||
42 | - | ||
43 | - h1 { | ||
44 | - height: 1300px; | ||
45 | - margin: 20px 0; | ||
46 | - } | ||
47 | - } | ||
48 | - | ||
49 | - .custom-enter { | ||
50 | - transform: scale(0.4) translate(100%); | ||
51 | - opacity: 0; | ||
52 | - } | ||
53 | - | ||
54 | - .custom-enter-to { | ||
55 | - opacity: 1; | ||
56 | - } | ||
57 | - | ||
58 | - .custom-enter-active { | ||
59 | - position: absolute; | ||
60 | - top: 0; | ||
61 | - width: 100%; | ||
62 | - transition: all 0.5s; | ||
63 | - } | ||
64 | - | ||
65 | - .custom-leave { | ||
66 | - opacity: 1; | ||
67 | - } | ||
68 | - | ||
69 | - .custom-leave-to { | ||
70 | - transform: scale(0.4) translate(-100%); | ||
71 | - opacity: 0; | ||
72 | - } | ||
73 | - | ||
74 | - .custom-leave-active { | ||
75 | - transition: all 0.5s; | ||
76 | - } | ||
77 | -</style> |
src/views/demo/comp/lazy/index.vue deleted
100644 → 0
1 | -<template> | ||
2 | - <PageWrapper title="懒加载基础示例" content="向下滚动到可见区域才会加载组件"> | ||
3 | - <div class="lazy-base-demo-wrap"> | ||
4 | - <h1>向下滚动</h1> | ||
5 | - | ||
6 | - <div class="lazy-base-demo-box"> | ||
7 | - <LazyContainer> | ||
8 | - <TargetContent /> | ||
9 | - <template #skeleton> | ||
10 | - <Skeleton :rows="10" /> | ||
11 | - </template> | ||
12 | - </LazyContainer> | ||
13 | - </div> | ||
14 | - </div> | ||
15 | - </PageWrapper> | ||
16 | -</template> | ||
17 | -<script lang="ts"> | ||
18 | - import { defineComponent } from 'vue'; | ||
19 | - import { Skeleton } from 'ant-design-vue'; | ||
20 | - import TargetContent from './TargetContent.vue'; | ||
21 | - import { LazyContainer } from '/@/components/Container/index'; | ||
22 | - import { PageWrapper } from '/@/components/Page'; | ||
23 | - | ||
24 | - export default defineComponent({ | ||
25 | - components: { LazyContainer, PageWrapper, TargetContent, Skeleton }, | ||
26 | - }); | ||
27 | -</script> | ||
28 | -<style lang="less"> | ||
29 | - .lazy-base-demo { | ||
30 | - &-wrap { | ||
31 | - display: flex; | ||
32 | - flex-direction: column; | ||
33 | - align-items: center; | ||
34 | - justify-content: center; | ||
35 | - width: 50%; | ||
36 | - height: 2000px; | ||
37 | - margin: 20px auto; | ||
38 | - background-color: @component-background; | ||
39 | - text-align: center; | ||
40 | - } | ||
41 | - | ||
42 | - &-box { | ||
43 | - width: 300px; | ||
44 | - height: 300px; | ||
45 | - } | ||
46 | - | ||
47 | - h1 { | ||
48 | - height: 1300px; | ||
49 | - margin: 20px 0; | ||
50 | - } | ||
51 | - } | ||
52 | -</style> |