Commit 0f4b847d69e90e5bbb4fb0883fb5ea1dd1daf1e7

Authored by vben
1 parent e79e540b

perf(lazy-container): optimize lazyContainer code

.browserslistrc deleted 100644 → 0
1 -> 1%  
2 -last 2 versions  
3 -not ie <= 10  
CHANGELOG.zh_CN.md
@@ -2,7 +2,8 @@ @@ -2,7 +2,8 @@
2 2
3 ### ⚡ Performance Improvements 3 ### ⚡ Performance Improvements
4 4
5 -- 菜单性能继续优化 5 +- 菜单性能继续优化,更流畅
  6 +- 优化懒加载组件及示例
6 7
7 ### 🎫 Chores 8 ### 🎫 Chores
8 9
@@ -13,6 +14,7 @@ @@ -13,6 +14,7 @@
13 ### 🐛 Bug Fixes 14 ### 🐛 Bug Fixes
14 15
15 - 修复升级之后 table 类型问题 16 - 修复升级之后 table 类型问题
  17 +- 修复分割菜单且左侧菜单没有数据时候,继续展示上一次子菜单的问题
16 18
17 ## 2.0.0-rc.8 (2020-11-2) 19 ## 2.0.0-rc.8 (2020-11-2)
18 20
src/components/Container/src/LazyContainer.vue
1 <template> 1 <template>
2 - <transition-group v-bind="$attrs" ref="elRef" :name="transitionName" :tag="tag"> 2 + <transition-group
  3 + class="lazy-container"
  4 + v-bind="$attrs"
  5 + ref="elRef"
  6 + :name="transitionName"
  7 + :tag="tag"
  8 + mode="out-in"
  9 + >
3 <div key="component" v-if="isInit"> 10 <div key="component" v-if="isInit">
4 <slot :loading="loading" /> 11 <slot :loading="loading" />
5 </div> 12 </div>
6 - <div key="skeleton"> 13 + <div key="skeleton" v-else name="lazy-skeleton">
7 <slot name="skeleton" v-if="$slots.skeleton" /> 14 <slot name="skeleton" v-if="$slots.skeleton" />
8 <Skeleton v-else /> 15 <Skeleton v-else />
9 </div> 16 </div>
@@ -12,19 +19,9 @@ @@ -12,19 +19,9 @@
12 <script lang="ts"> 19 <script lang="ts">
13 import type { PropType } from 'vue'; 20 import type { PropType } from 'vue';
14 21
15 - import {  
16 - defineComponent,  
17 - reactive,  
18 - onMounted,  
19 - ref,  
20 - unref,  
21 - onUnmounted,  
22 - toRef,  
23 - toRefs,  
24 - } from 'vue'; 22 + import { defineComponent, reactive, onMounted, ref, toRef, toRefs } from 'vue';
25 23
26 import { Skeleton } from 'ant-design-vue'; 24 import { Skeleton } from 'ant-design-vue';
27 - import { useRaf } from '/@/hooks/event/useRaf';  
28 import { useTimeout } from '/@/hooks/core/useTimeout'; 25 import { useTimeout } from '/@/hooks/core/useTimeout';
29 import { useIntersectionObserver } from '/@/hooks/event/useIntersectionObserver'; 26 import { useIntersectionObserver } from '/@/hooks/event/useIntersectionObserver';
30 interface State { 27 interface State {
@@ -36,13 +33,12 @@ @@ -36,13 +33,12 @@
36 name: 'LazyContainer', 33 name: 'LazyContainer',
37 components: { Skeleton }, 34 components: { Skeleton },
38 props: { 35 props: {
39 - // 等待时间,如果指定了时间,不论可见与否,在指定时间之后自动加载 36 + // Waiting time, if the time is specified, whether visible or not, it will be automatically loaded after the specified time
40 timeout: { 37 timeout: {
41 type: Number as PropType<number>, 38 type: Number as PropType<number>,
42 - default: 0,  
43 - // default: 8000,  
44 }, 39 },
45 - // 组件所在的视口,如果组件是在页面容器内滚动,视口就是该容器 40 +
  41 + // The viewport where the component is located. If the component is scrolling in the page container, the viewport is the container
46 viewport: { 42 viewport: {
47 type: (typeof window !== 'undefined' ? window.HTMLElement : Object) as PropType< 43 type: (typeof window !== 'undefined' ? window.HTMLElement : Object) as PropType<
48 HTMLElement 44 HTMLElement
@@ -50,19 +46,19 @@ @@ -50,19 +46,19 @@
50 default: () => null, 46 default: () => null,
51 }, 47 },
52 48
53 - // 预加载阈值, css单位 49 + // Preload threshold, css unit
54 threshold: { 50 threshold: {
55 type: String as PropType<string>, 51 type: String as PropType<string>,
56 default: '0px', 52 default: '0px',
57 }, 53 },
58 54
59 - // 视口的滚动方向, vertical代表垂直方向,horizontal代表水平方向 55 + // The scroll direction of the viewport, vertical represents the vertical direction, horizontal represents the horizontal direction
60 direction: { 56 direction: {
61 type: String as PropType<'vertical' | 'horizontal'>, 57 type: String as PropType<'vertical' | 'horizontal'>,
62 default: 'vertical', 58 default: 'vertical',
63 }, 59 },
64 60
65 - // 包裹组件的外层容器的标签名 61 + // The label name of the outer container that wraps the component
66 tag: { 62 tag: {
67 type: String as PropType<string>, 63 type: String as PropType<string>,
68 default: 'div', 64 default: 'div',
@@ -105,23 +101,11 @@ @@ -105,23 +101,11 @@
105 function init() { 101 function init() {
106 state.loading = true; 102 state.loading = true;
107 103
108 - requestAnimationFrameFn(() => {  
109 - state.isInit = true;  
110 - emit('init');  
111 - });  
112 - }  
113 -  
114 - function requestAnimationFrameFn(callback: () => any) {  
115 - // Prevent waiting too long without executing the callback  
116 - // Set the maximum waiting time  
117 useTimeout(() => { 104 useTimeout(() => {
118 if (state.isInit) return; 105 if (state.isInit) return;
119 - callback(); 106 + state.isInit = true;
  107 + emit('init');
120 }, props.maxWaitingTime || 80); 108 }, props.maxWaitingTime || 80);
121 -  
122 - const { requestAnimationFrame } = useRaf();  
123 -  
124 - return requestAnimationFrame;  
125 } 109 }
126 110
127 function initIntersectionObserver() { 111 function initIntersectionObserver() {
@@ -165,31 +149,8 @@ @@ -165,31 +149,8 @@
165 }); 149 });
166 </script> 150 </script>
167 <style lang="less"> 151 <style lang="less">
168 - .lazy-container-enter {  
169 - opacity: 0;  
170 - }  
171 -  
172 - .lazy-container-enter-to {  
173 - opacity: 1;  
174 - }  
175 -  
176 - .lazy-container-enter-from,  
177 - .lazy-container-enter-active {  
178 - position: absolute;  
179 - top: 0; 152 + .lazy-container {
180 width: 100%; 153 width: 100%;
181 - transition: opacity 0.3s 0.2s;  
182 - }  
183 -  
184 - .lazy-container-leave {  
185 - opacity: 1;  
186 - }  
187 -  
188 - .lazy-container-leave-to {  
189 - opacity: 0;  
190 - }  
191 -  
192 - .lazy-container-leave-active {  
193 - transition: opacity 0.5s; 154 + height: 100%;
194 } 155 }
195 </style> 156 </style>
src/components/Container/src/collapse/CollapseContainer.vue
@@ -8,13 +8,13 @@ @@ -8,13 +8,13 @@
8 <CollapseTransition :enable="canExpan"> 8 <CollapseTransition :enable="canExpan">
9 <Skeleton v-if="loading" /> 9 <Skeleton v-if="loading" />
10 <div class="collapse-container__body" v-else v-show="show"> 10 <div class="collapse-container__body" v-else v-show="show">
11 - <!-- <LazyContainer :timeout="lazyTime" v-if="lazy"> 11 + <LazyContainer :timeout="lazyTime" v-if="lazy">
12 <slot /> 12 <slot />
13 <template #skeleton> 13 <template #skeleton>
14 <slot name="lazySkeleton" /> 14 <slot name="lazySkeleton" />
15 </template> 15 </template>
16 - </LazyContainer> -->  
17 - <slot /> 16 + </LazyContainer>
  17 + <slot v-else />
18 </div> 18 </div>
19 </CollapseTransition> 19 </CollapseTransition>
20 </div> 20 </div>
@@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
28 import CollapseHeader from './CollapseHeader.vue'; 28 import CollapseHeader from './CollapseHeader.vue';
29 import { Skeleton } from 'ant-design-vue'; 29 import { Skeleton } from 'ant-design-vue';
30 30
31 - // import LazyContainer from '../LazyContainer'; 31 + import LazyContainer from '../LazyContainer.vue';
32 32
33 import { triggerWindowResize } from '/@/utils/event/triggerWindowResizeEvent'; 33 import { triggerWindowResize } from '/@/utils/event/triggerWindowResizeEvent';
34 // hook 34 // hook
@@ -36,7 +36,7 @@ @@ -36,7 +36,7 @@
36 export default defineComponent({ 36 export default defineComponent({
37 components: { 37 components: {
38 Skeleton, 38 Skeleton,
39 - // LazyContainer, 39 + LazyContainer,
40 CollapseHeader, 40 CollapseHeader,
41 CollapseTransition, 41 CollapseTransition,
42 }, 42 },
@@ -75,7 +75,7 @@ @@ -75,7 +75,7 @@
75 // 延时加载时间 75 // 延时加载时间
76 lazyTime: { 76 lazyTime: {
77 type: Number as PropType<number>, 77 type: Number as PropType<number>,
78 - default: 3000, 78 + default: 0,
79 }, 79 },
80 }, 80 },
81 setup(props) { 81 setup(props) {
src/components/ContextMenu/src/index.tsx
@@ -25,11 +25,13 @@ export default defineComponent({ @@ -25,11 +25,13 @@ export default defineComponent({
25 const state = reactive({ 25 const state = reactive({
26 show: false, 26 show: false,
27 }); 27 });
  28 +
28 onMounted(() => { 29 onMounted(() => {
29 nextTick(() => { 30 nextTick(() => {
30 state.show = true; 31 state.show = true;
31 }); 32 });
32 }); 33 });
  34 +
33 onUnmounted(() => { 35 onUnmounted(() => {
34 const el = unref(wrapRef); 36 const el = unref(wrapRef);
35 el && document.body.removeChild(el); 37 el && document.body.removeChild(el);
@@ -61,6 +63,7 @@ export default defineComponent({ @@ -61,6 +63,7 @@ export default defineComponent({
61 63
62 handler && handler(); 64 handler && handler();
63 } 65 }
  66 +
64 function renderContent(item: ContextMenuItem) { 67 function renderContent(item: ContextMenuItem) {
65 const { icon, label } = item; 68 const { icon, label } = item;
66 69
@@ -72,6 +75,7 @@ export default defineComponent({ @@ -72,6 +75,7 @@ export default defineComponent({
72 </span> 75 </span>
73 ); 76 );
74 } 77 }
  78 +
75 function renderMenuItem(items: ContextMenuItem[]) { 79 function renderMenuItem(items: ContextMenuItem[]) {
76 return items.map((item, index) => { 80 return items.map((item, index) => {
77 const { disabled, label, children, divider = false } = item; 81 const { disabled, label, children, divider = false } = item;
src/components/Preview/src/index.tsx
@@ -265,6 +265,7 @@ export default defineComponent({ @@ -265,6 +265,7 @@ export default defineComponent({
265 </div> 265 </div>
266 ); 266 );
267 }; 267 };
  268 +
268 return () => { 269 return () => {
269 return ( 270 return (
270 imgState.show && ( 271 imgState.show && (
src/router/menus/modules/demo/comp.ts
@@ -19,6 +19,26 @@ const menu: MenuModule = { @@ -19,6 +19,26 @@ const menu: MenuModule = {
19 }, 19 },
20 20
21 { 21 {
  22 + path: 'modal',
  23 + name: '弹窗扩展',
  24 + },
  25 + {
  26 + path: 'drawer',
  27 + name: '抽屉扩展',
  28 + },
  29 + {
  30 + path: 'desc',
  31 + name: '详情组件',
  32 + },
  33 + {
  34 + path: 'qrcode',
  35 + name: '二维码组件',
  36 + },
  37 + {
  38 + path: 'strength-meter',
  39 + name: '密码强度组件',
  40 + },
  41 + {
22 path: 'scroll', 42 path: 'scroll',
23 name: '滚动组件', 43 name: '滚动组件',
24 children: [ 44 children: [
@@ -37,20 +57,18 @@ const menu: MenuModule = { @@ -37,20 +57,18 @@ const menu: MenuModule = {
37 ], 57 ],
38 }, 58 },
39 { 59 {
40 - path: 'modal',  
41 - name: '弹窗扩展',  
42 - },  
43 - {  
44 - path: 'drawer',  
45 - name: '抽屉扩展',  
46 - },  
47 - {  
48 - path: 'desc',  
49 - name: '详情组件',  
50 - },  
51 - {  
52 path: 'lazy', 60 path: 'lazy',
53 name: '懒加载组件', 61 name: '懒加载组件',
  62 + children: [
  63 + {
  64 + path: 'basic',
  65 + name: '基础示例',
  66 + },
  67 + {
  68 + path: 'transition',
  69 + name: '动画效果',
  70 + },
  71 + ],
54 }, 72 },
55 { 73 {
56 path: 'verify', 74 path: 'verify',
@@ -66,14 +84,6 @@ const menu: MenuModule = { @@ -66,14 +84,6 @@ const menu: MenuModule = {
66 }, 84 },
67 ], 85 ],
68 }, 86 },
69 - {  
70 - path: 'qrcode',  
71 - name: '二维码组件',  
72 - },  
73 - {  
74 - path: 'strength-meter',  
75 - name: '密码强度组件',  
76 - },  
77 ], 87 ],
78 }, 88 },
79 }; 89 };
src/router/routes/modules/demo/comp.ts
@@ -99,13 +99,32 @@ export default { @@ -99,13 +99,32 @@ export default {
99 title: '详情组件', 99 title: '详情组件',
100 }, 100 },
101 }, 101 },
  102 +
102 { 103 {
103 path: '/lazy', 104 path: '/lazy',
104 name: 'lazyDemo', 105 name: 'lazyDemo',
105 - component: () => import('/@/views/demo/comp/lazy/index.vue'), 106 + redirect: '/comp/lazy/basic',
106 meta: { 107 meta: {
107 title: '懒加载组件', 108 title: '懒加载组件',
108 }, 109 },
  110 + children: [
  111 + {
  112 + path: 'basic',
  113 + name: 'BasicLazyDemo',
  114 + component: () => import('/@/views/demo/comp/lazy/index.vue'),
  115 + meta: {
  116 + title: '基础示例',
  117 + },
  118 + },
  119 + {
  120 + path: 'transition',
  121 + name: 'BasicTransitionDemo',
  122 + component: () => import('/@/views/demo/comp/lazy/Transition.vue'),
  123 + meta: {
  124 + title: '动画效果',
  125 + },
  126 + },
  127 + ],
109 }, 128 },
110 { 129 {
111 path: '/verify', 130 path: '/verify',
src/views/demo/comp/lazy/Transition.vue 0 → 100644
  1 +<template>
  2 + <div class="p-4 lazy-base-demo">
  3 + <Alert message="自定义动画" description="懒加载组件显示动画" type="info" show-icon />
  4 + <div class="lazy-base-demo-wrap">
  5 + <h1>向下滚动</h1>
  6 +
  7 + <div class="lazy-base-demo-box">
  8 + <LazyContainer transitionName="custom">
  9 + <TargetContent />
  10 + </LazyContainer>
  11 + </div>
  12 + </div>
  13 + </div>
  14 +</template>
  15 +<script lang="ts">
  16 + import { defineComponent } from 'vue';
  17 + import { Skeleton, Alert } from 'ant-design-vue';
  18 + import TargetContent from './TargetContent.vue';
  19 + import { LazyContainer } from '/@/components/Container/index';
  20 + export default defineComponent({
  21 + components: { LazyContainer, TargetContent, Skeleton, Alert },
  22 + setup() {
  23 + return {};
  24 + },
  25 + });
  26 +</script>
  27 +<style lang="less">
  28 + .lazy-base-demo {
  29 + &-wrap {
  30 + display: flex;
  31 + width: 50%;
  32 + height: 2000px;
  33 + margin: 20px auto;
  34 + text-align: center;
  35 + background: #fff;
  36 + justify-content: center;
  37 + flex-direction: column;
  38 + align-items: center;
  39 + }
  40 +
  41 + &-box {
  42 + width: 300px;
  43 + height: 300px;
  44 + }
  45 +
  46 + h1 {
  47 + height: 1300px;
  48 + margin: 20px 0;
  49 + }
  50 + }
  51 +
  52 + .custom-enter {
  53 + opacity: 0;
  54 + transform: scale(0.4) translate(100%);
  55 + }
  56 +
  57 + .custom-enter-to {
  58 + opacity: 1;
  59 + }
  60 +
  61 + .custom-enter-active {
  62 + position: absolute;
  63 + top: 0;
  64 + width: 100%;
  65 + transition: all 0.5s;
  66 + }
  67 +
  68 + .custom-leave {
  69 + opacity: 1;
  70 + }
  71 +
  72 + .custom-leave-to {
  73 + opacity: 0;
  74 + transform: scale(0.4) translate(-100%);
  75 + }
  76 +
  77 + .custom-leave-active {
  78 + transition: all 0.5s;
  79 + }
  80 +</style>
src/views/demo/comp/lazy/index.vue
@@ -3,12 +3,15 @@ @@ -3,12 +3,15 @@
3 <Alert message="基础示例" description="向下滚动到可见区域才会加载组件" type="info" show-icon /> 3 <Alert message="基础示例" description="向下滚动到可见区域才会加载组件" type="info" show-icon />
4 <div class="lazy-base-demo-wrap"> 4 <div class="lazy-base-demo-wrap">
5 <h1>向下滚动</h1> 5 <h1>向下滚动</h1>
6 - <LazyContainer @init="() => {}">  
7 - <TargetContent />  
8 - <template #skeleton>  
9 - <Skeleton :rows="10" />  
10 - </template>  
11 - </LazyContainer> 6 +
  7 + <div class="lazy-base-demo-box">
  8 + <LazyContainer>
  9 + <TargetContent />
  10 + <template #skeleton>
  11 + <Skeleton :rows="10" />
  12 + </template>
  13 + </LazyContainer>
  14 + </div>
12 </div> 15 </div>
13 </div> 16 </div>
14 </template> 17 </template>
@@ -24,7 +27,7 @@ @@ -24,7 +27,7 @@
24 }, 27 },
25 }); 28 });
26 </script> 29 </script>
27 -<style lang="less" scoped> 30 +<style lang="less">
28 .lazy-base-demo { 31 .lazy-base-demo {
29 &-wrap { 32 &-wrap {
30 display: flex; 33 display: flex;
@@ -38,6 +41,11 @@ @@ -38,6 +41,11 @@
38 align-items: center; 41 align-items: center;
39 } 42 }
40 43
  44 + &-box {
  45 + width: 300px;
  46 + height: 300px;
  47 + }
  48 +
41 h1 { 49 h1 {
42 height: 1300px; 50 height: 1300px;
43 margin: 20px 0; 51 margin: 20px 0;