Browse Source

perf(lazy-container): optimize lazyContainer code

vben 4 years ago
parent
commit
0f4b847d69

+ 0 - 3
.browserslistrc

@@ -1,3 +0,0 @@
-> 1%
-last 2 versions
-not ie <= 10

+ 3 - 1
CHANGELOG.zh_CN.md

@@ -2,7 +2,8 @@
 
 ### ⚡ Performance Improvements
 
-- 菜单性能继续优化
+- 菜单性能继续优化,更流畅
+- 优化懒加载组件及示例
 
 ### 🎫 Chores
 
@@ -13,6 +14,7 @@
 ### 🐛 Bug Fixes
 
 - 修复升级之后 table 类型问题
+- 修复分割菜单且左侧菜单没有数据时候,继续展示上一次子菜单的问题
 
 ## 2.0.0-rc.8 (2020-11-2)
 

+ 20 - 59
src/components/Container/src/LazyContainer.vue

@@ -1,9 +1,16 @@
 <template>
-  <transition-group v-bind="$attrs" ref="elRef" :name="transitionName" :tag="tag">
+  <transition-group
+    class="lazy-container"
+    v-bind="$attrs"
+    ref="elRef"
+    :name="transitionName"
+    :tag="tag"
+    mode="out-in"
+  >
     <div key="component" v-if="isInit">
       <slot :loading="loading" />
     </div>
-    <div key="skeleton">
+    <div key="skeleton" v-else name="lazy-skeleton">
       <slot name="skeleton" v-if="$slots.skeleton" />
       <Skeleton v-else />
     </div>
@@ -12,19 +19,9 @@
 <script lang="ts">
   import type { PropType } from 'vue';
 
-  import {
-    defineComponent,
-    reactive,
-    onMounted,
-    ref,
-    unref,
-    onUnmounted,
-    toRef,
-    toRefs,
-  } from 'vue';
+  import { defineComponent, reactive, onMounted, ref, toRef, toRefs } from 'vue';
 
   import { Skeleton } from 'ant-design-vue';
-  import { useRaf } from '/@/hooks/event/useRaf';
   import { useTimeout } from '/@/hooks/core/useTimeout';
   import { useIntersectionObserver } from '/@/hooks/event/useIntersectionObserver';
   interface State {
@@ -36,13 +33,12 @@
     name: 'LazyContainer',
     components: { Skeleton },
     props: {
-      // 等待时间,如果指定了时间,不论可见与否,在指定时间之后自动加载
+      // Waiting time, if the time is specified, whether visible or not, it will be automatically loaded after the specified time
       timeout: {
         type: Number as PropType<number>,
-        default: 0,
-        // default: 8000,
       },
-      // 组件所在的视口,如果组件是在页面容器内滚动,视口就是该容器
+
+      // The viewport where the component is located. If the component is scrolling in the page container, the viewport is the container
       viewport: {
         type: (typeof window !== 'undefined' ? window.HTMLElement : Object) as PropType<
           HTMLElement
@@ -50,19 +46,19 @@
         default: () => null,
       },
 
-      // 预加载阈值, css单位
+      // Preload threshold, css unit
       threshold: {
         type: String as PropType<string>,
         default: '0px',
       },
 
-      // 视口的滚动方向, vertical代表垂直方向,horizontal代表水平方向
+      // The scroll direction of the viewport, vertical represents the vertical direction, horizontal represents the horizontal direction
       direction: {
         type: String as PropType<'vertical' | 'horizontal'>,
         default: 'vertical',
       },
 
-      // 包裹组件的外层容器的标签名
+      // The label name of the outer container that wraps the component
       tag: {
         type: String as PropType<string>,
         default: 'div',
@@ -105,23 +101,11 @@
       function init() {
         state.loading = true;
 
-        requestAnimationFrameFn(() => {
-          state.isInit = true;
-          emit('init');
-        });
-      }
-
-      function requestAnimationFrameFn(callback: () => any) {
-        // Prevent waiting too long without executing the callback
-        // Set the maximum waiting time
         useTimeout(() => {
           if (state.isInit) return;
-          callback();
+          state.isInit = true;
+          emit('init');
         }, props.maxWaitingTime || 80);
-
-        const { requestAnimationFrame } = useRaf();
-
-        return requestAnimationFrame;
       }
 
       function initIntersectionObserver() {
@@ -165,31 +149,8 @@
   });
 </script>
 <style lang="less">
-  .lazy-container-enter {
-    opacity: 0;
-  }
-
-  .lazy-container-enter-to {
-    opacity: 1;
-  }
-
-  .lazy-container-enter-from,
-  .lazy-container-enter-active {
-    position: absolute;
-    top: 0;
+  .lazy-container {
     width: 100%;
-    transition: opacity 0.3s 0.2s;
-  }
-
-  .lazy-container-leave {
-    opacity: 1;
-  }
-
-  .lazy-container-leave-to {
-    opacity: 0;
-  }
-
-  .lazy-container-leave-active {
-    transition: opacity 0.5s;
+    height: 100%;
   }
 </style>

+ 6 - 6
src/components/Container/src/collapse/CollapseContainer.vue

@@ -8,13 +8,13 @@
     <CollapseTransition :enable="canExpan">
       <Skeleton v-if="loading" />
       <div class="collapse-container__body" v-else v-show="show">
-        <!-- <LazyContainer :timeout="lazyTime" v-if="lazy">
+        <LazyContainer :timeout="lazyTime" v-if="lazy">
           <slot />
           <template #skeleton>
             <slot name="lazySkeleton" />
           </template>
-        </LazyContainer> -->
-        <slot />
+        </LazyContainer>
+        <slot v-else />
       </div>
     </CollapseTransition>
   </div>
@@ -28,7 +28,7 @@
   import CollapseHeader from './CollapseHeader.vue';
   import { Skeleton } from 'ant-design-vue';
 
-  // import LazyContainer from '../LazyContainer';
+  import LazyContainer from '../LazyContainer.vue';
 
   import { triggerWindowResize } from '/@/utils/event/triggerWindowResizeEvent';
   // hook
@@ -36,7 +36,7 @@
   export default defineComponent({
     components: {
       Skeleton,
-      // LazyContainer,
+      LazyContainer,
       CollapseHeader,
       CollapseTransition,
     },
@@ -75,7 +75,7 @@
       // 延时加载时间
       lazyTime: {
         type: Number as PropType<number>,
-        default: 3000,
+        default: 0,
       },
     },
     setup(props) {

+ 4 - 0
src/components/ContextMenu/src/index.tsx

@@ -25,11 +25,13 @@ export default defineComponent({
     const state = reactive({
       show: false,
     });
+
     onMounted(() => {
       nextTick(() => {
         state.show = true;
       });
     });
+
     onUnmounted(() => {
       const el = unref(wrapRef);
       el && document.body.removeChild(el);
@@ -61,6 +63,7 @@ export default defineComponent({
 
       handler && handler();
     }
+
     function renderContent(item: ContextMenuItem) {
       const { icon, label } = item;
 
@@ -72,6 +75,7 @@ export default defineComponent({
         </span>
       );
     }
+
     function renderMenuItem(items: ContextMenuItem[]) {
       return items.map((item, index) => {
         const { disabled, label, children, divider = false } = item;

+ 1 - 0
src/components/Preview/src/index.tsx

@@ -265,6 +265,7 @@ export default defineComponent({
         </div>
       );
     };
+
     return () => {
       return (
         imgState.show && (

+ 30 - 20
src/router/menus/modules/demo/comp.ts

@@ -19,6 +19,26 @@ const menu: MenuModule = {
       },
 
       {
+        path: 'modal',
+        name: '弹窗扩展',
+      },
+      {
+        path: 'drawer',
+        name: '抽屉扩展',
+      },
+      {
+        path: 'desc',
+        name: '详情组件',
+      },
+      {
+        path: 'qrcode',
+        name: '二维码组件',
+      },
+      {
+        path: 'strength-meter',
+        name: '密码强度组件',
+      },
+      {
         path: 'scroll',
         name: '滚动组件',
         children: [
@@ -37,20 +57,18 @@ const menu: MenuModule = {
         ],
       },
       {
-        path: 'modal',
-        name: '弹窗扩展',
-      },
-      {
-        path: 'drawer',
-        name: '抽屉扩展',
-      },
-      {
-        path: 'desc',
-        name: '详情组件',
-      },
-      {
         path: 'lazy',
         name: '懒加载组件',
+        children: [
+          {
+            path: 'basic',
+            name: '基础示例',
+          },
+          {
+            path: 'transition',
+            name: '动画效果',
+          },
+        ],
       },
       {
         path: 'verify',
@@ -66,14 +84,6 @@ const menu: MenuModule = {
           },
         ],
       },
-      {
-        path: 'qrcode',
-        name: '二维码组件',
-      },
-      {
-        path: 'strength-meter',
-        name: '密码强度组件',
-      },
     ],
   },
 };

+ 20 - 1
src/router/routes/modules/demo/comp.ts

@@ -99,13 +99,32 @@ export default {
         title: '详情组件',
       },
     },
+
     {
       path: '/lazy',
       name: 'lazyDemo',
-      component: () => import('/@/views/demo/comp/lazy/index.vue'),
+      redirect: '/comp/lazy/basic',
       meta: {
         title: '懒加载组件',
       },
+      children: [
+        {
+          path: 'basic',
+          name: 'BasicLazyDemo',
+          component: () => import('/@/views/demo/comp/lazy/index.vue'),
+          meta: {
+            title: '基础示例',
+          },
+        },
+        {
+          path: 'transition',
+          name: 'BasicTransitionDemo',
+          component: () => import('/@/views/demo/comp/lazy/Transition.vue'),
+          meta: {
+            title: '动画效果',
+          },
+        },
+      ],
     },
     {
       path: '/verify',

+ 80 - 0
src/views/demo/comp/lazy/Transition.vue

@@ -0,0 +1,80 @@
+<template>
+  <div class="p-4 lazy-base-demo">
+    <Alert message="自定义动画" description="懒加载组件显示动画" type="info" show-icon />
+    <div class="lazy-base-demo-wrap">
+      <h1>向下滚动</h1>
+
+      <div class="lazy-base-demo-box">
+        <LazyContainer transitionName="custom">
+          <TargetContent />
+        </LazyContainer>
+      </div>
+    </div>
+  </div>
+</template>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { Skeleton, Alert } from 'ant-design-vue';
+  import TargetContent from './TargetContent.vue';
+  import { LazyContainer } from '/@/components/Container/index';
+  export default defineComponent({
+    components: { LazyContainer, TargetContent, Skeleton, Alert },
+    setup() {
+      return {};
+    },
+  });
+</script>
+<style lang="less">
+  .lazy-base-demo {
+    &-wrap {
+      display: flex;
+      width: 50%;
+      height: 2000px;
+      margin: 20px auto;
+      text-align: center;
+      background: #fff;
+      justify-content: center;
+      flex-direction: column;
+      align-items: center;
+    }
+
+    &-box {
+      width: 300px;
+      height: 300px;
+    }
+
+    h1 {
+      height: 1300px;
+      margin: 20px 0;
+    }
+  }
+
+  .custom-enter {
+    opacity: 0;
+    transform: scale(0.4) translate(100%);
+  }
+
+  .custom-enter-to {
+    opacity: 1;
+  }
+
+  .custom-enter-active {
+    position: absolute;
+    top: 0;
+    width: 100%;
+    transition: all 0.5s;
+  }
+
+  .custom-leave {
+    opacity: 1;
+  }
+
+  .custom-leave-to {
+    opacity: 0;
+    transform: scale(0.4) translate(-100%);
+  }
+
+  .custom-leave-active {
+    transition: all 0.5s;
+  }
+</style>

+ 15 - 7
src/views/demo/comp/lazy/index.vue

@@ -3,12 +3,15 @@
     <Alert message="基础示例" description="向下滚动到可见区域才会加载组件" type="info" show-icon />
     <div class="lazy-base-demo-wrap">
       <h1>向下滚动</h1>
-      <LazyContainer @init="() => {}">
-        <TargetContent />
-        <template #skeleton>
-          <Skeleton :rows="10" />
-        </template>
-      </LazyContainer>
+
+      <div class="lazy-base-demo-box">
+        <LazyContainer>
+          <TargetContent />
+          <template #skeleton>
+            <Skeleton :rows="10" />
+          </template>
+        </LazyContainer>
+      </div>
     </div>
   </div>
 </template>
@@ -24,7 +27,7 @@
     },
   });
 </script>
-<style lang="less" scoped>
+<style lang="less">
   .lazy-base-demo {
     &-wrap {
       display: flex;
@@ -38,6 +41,11 @@
       align-items: center;
     }
 
+    &-box {
+      width: 300px;
+      height: 300px;
+    }
+
     h1 {
       height: 1300px;
       margin: 20px 0;