Sfoglia il codice sorgente

refactor(virtual-scroll): refactor virtualScroll component

Vben 3 anni fa
parent
commit
3b2c40bec8

+ 4 - 3
src/components/Markdown/index.ts

@@ -1,4 +1,5 @@
-import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
-export const MarkDown = createAsyncComponent(() => import('./src/Markdown.vue'));
+import { withInstall } from '/@/utils';
+import markDown from './src/Markdown.vue';
 
-export * from './src/types';
+export const MarkDown = withInstall(markDown);
+export * from './src/typing';

+ 3 - 4
src/components/Markdown/src/Markdown.vue

@@ -14,18 +14,17 @@
   } from 'vue';
   import Vditor from 'vditor';
   import 'vditor/dist/index.css';
-
-  import { propTypes } from '/@/utils/propTypes';
   import { useLocale } from '/@/locales/useLocale';
   import { useModalContext } from '../../Modal';
   import { useRootSetting } from '/@/hooks/setting/useRootSetting';
 
   type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
+
   export default defineComponent({
     inheritAttrs: false,
     props: {
-      height: propTypes.number.def(360),
-      value: propTypes.string.def(''),
+      height: { type: Number, default: 360 },
+      value: { type: String, default: '' },
     },
     emits: ['change', 'get'],
     setup(props, { attrs, emit }) {

+ 0 - 0
src/components/Markdown/src/types.ts → src/components/Markdown/src/typing.ts


+ 4 - 1
src/components/StrengthMeter/index.ts

@@ -1 +1,4 @@
-export { default as StrengthMeter } from './src/StrengthMeter.vue';
+import { withInstall } from '/@/utils';
+import strengthMeter from './src/StrengthMeter.vue';
+
+export const StrengthMeter = withInstall(strengthMeter);

+ 0 - 3
src/components/StrengthMeter/src/StrengthMeter.vue

@@ -20,10 +20,7 @@
 
 <script lang="ts">
   import { defineComponent, computed, ref, watch, unref, watchEffect } from 'vue';
-
   import { Input } from 'ant-design-vue';
-
-  // @ts-ignore
   import { zxcvbn } from '@zxcvbn-ts/core';
   import { useDesign } from '/@/hooks/web/useDesign';
   import { propTypes } from '/@/utils/propTypes';

+ 4 - 1
src/components/Time/index.ts

@@ -1 +1,4 @@
-export { default as Time } from './src/Time.vue';
+import { withInstall } from '/@/utils/index';
+import time from './src/Time.vue';
+
+export const Time = withInstall(time);

+ 1 - 2
src/components/Time/src/Time.vue

@@ -3,10 +3,8 @@
 </template>
 <script lang="ts">
   import { defineComponent, ref, watch } from 'vue';
-
   import { useI18n } from '/@/hooks/web/useI18n';
   import { useIntervalFn } from '@vueuse/core';
-
   import { formatToDateTime, formatToDate, dateUtil } from '/@/utils/dateUtil';
   import { isNumber, isObject, isString } from '/@/utils/is';
   import { propTypes } from '/@/utils/propTypes';
@@ -15,6 +13,7 @@
   const ONE_MINUTES = ONE_SECONDS * 60;
   const ONE_HOUR = ONE_MINUTES * 60;
   const ONE_DAY = ONE_HOUR * 24;
+
   export default defineComponent({
     name: 'Time',
     props: {

+ 4 - 2
src/components/Tinymce/index.ts

@@ -1,2 +1,4 @@
-import Tinymce from './src/Editor.vue';
-export { Tinymce };
+import { withInstall } from '/@/utils/index';
+import tinymce from './src/Editor.vue';
+
+export const Tinymce = withInstall(tinymce);

+ 0 - 5
src/components/Tinymce/src/Editor.vue

@@ -16,7 +16,6 @@
   import type { RawEditorSettings } from 'tinymce';
   import tinymce from 'tinymce/tinymce';
   import 'tinymce/themes/silver';
-
   import 'tinymce/icons/default/icons';
   import 'tinymce/plugins/advlist';
   import 'tinymce/plugins/anchor';
@@ -58,11 +57,8 @@
     onUnmounted,
     onDeactivated,
   } from 'vue';
-
   import ImgUpload from './ImgUpload.vue';
-
   import { toolbar, plugins } from './tinymce';
-
   import { buildShortUUID } from '/@/utils/uuid';
   import { bindHandlers } from './helper';
   import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
@@ -96,7 +92,6 @@
       required: false,
       default: 400,
     },
-
     width: {
       type: [Number, String] as PropType<string | number>,
       required: false,

+ 1 - 1
src/components/Tinymce/src/ImgUpload.vue

@@ -52,9 +52,9 @@
       function handleChange(info: Recordable) {
         const file = info.file;
         const status = file?.status;
-
         const url = file?.response?.url;
         const name = file?.name;
+
         if (status === 'uploading') {
           if (!uploading) {
             emit('uploading', name);

+ 3 - 2
src/components/VirtualScroll/index.ts

@@ -1,3 +1,4 @@
-import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
+import { withInstall } from '/@/utils/index';
+import vScroll from './src/VirtualScroll.vue';
 
-export const VScroll = createAsyncComponent(() => import('./src/VirtualScroll'));
+export const VScroll = withInstall(vScroll);

+ 0 - 148
src/components/VirtualScroll/src/VirtualScroll.tsx

@@ -1,148 +0,0 @@
-import {
-  defineComponent,
-  computed,
-  ref,
-  unref,
-  reactive,
-  onMounted,
-  watch,
-  nextTick,
-  CSSProperties,
-} from 'vue';
-import { useEventListener } from '/@/hooks/event/useEventListener';
-
-import { props as basicProps } from './props';
-import { getSlot } from '/@/utils/helper/tsxHelper';
-import './index.less';
-
-const prefixCls = 'virtual-scroll';
-
-function convertToUnit(str: string | number | null | undefined, unit = 'px'): string | undefined {
-  if (str == null || str === '') {
-    return undefined;
-  } else if (isNaN(+str!)) {
-    return String(str);
-  } else {
-    return `${Number(str)}${unit}`;
-  }
-}
-
-export default defineComponent({
-  name: 'VirtualScroll',
-  props: basicProps,
-  setup(props, { slots }) {
-    const wrapElRef = ref<HTMLDivElement | null>(null);
-    const state = reactive({
-      first: 0,
-      last: 0,
-      scrollTop: 0,
-    });
-
-    const getBenchRef = computed(() => {
-      return parseInt(props.bench as string, 10);
-    });
-
-    const getItemHeightRef = computed(() => {
-      return parseInt(props.itemHeight as string, 10);
-    });
-
-    const getFirstToRenderRef = computed(() => {
-      return Math.max(0, state.first - unref(getBenchRef));
-    });
-
-    const getLastToRenderRef = computed(() => {
-      return Math.min((props.items || []).length, state.last + unref(getBenchRef));
-    });
-
-    const getContainerStyleRef = computed((): CSSProperties => {
-      return {
-        height: convertToUnit((props.items || []).length * unref(getItemHeightRef)),
-      };
-    });
-
-    const getWrapStyleRef = computed((): CSSProperties => {
-      const styles: Recordable<string> = {};
-      const height = convertToUnit(props.height);
-      const minHeight = convertToUnit(props.minHeight);
-      const minWidth = convertToUnit(props.minWidth);
-      const maxHeight = convertToUnit(props.maxHeight);
-      const maxWidth = convertToUnit(props.maxWidth);
-      const width = convertToUnit(props.width);
-
-      if (height) styles.height = height;
-      if (minHeight) styles.minHeight = minHeight;
-      if (minWidth) styles.minWidth = minWidth;
-      if (maxHeight) styles.maxHeight = maxHeight;
-      if (maxWidth) styles.maxWidth = maxWidth;
-      if (width) styles.width = width;
-      return styles;
-    });
-
-    watch([() => props.itemHeight, () => props.height], () => {
-      onScroll();
-    });
-
-    function getLast(first: number): number {
-      const wrapEl = unref(wrapElRef);
-      if (!wrapEl) {
-        return 0;
-      }
-      const height = parseInt(props.height || 0, 10) || wrapEl.clientHeight;
-
-      return first + Math.ceil(height / unref(getItemHeightRef));
-    }
-
-    function getFirst(): number {
-      return Math.floor(state.scrollTop / unref(getItemHeightRef));
-    }
-
-    function onScroll() {
-      const wrapEl = unref(wrapElRef);
-      if (!wrapEl) {
-        return;
-      }
-      state.scrollTop = wrapEl.scrollTop;
-      state.first = getFirst();
-      state.last = getLast(state.first);
-    }
-
-    function renderChildren() {
-      const { items = [] } = props;
-      return items.slice(unref(getFirstToRenderRef), unref(getLastToRenderRef)).map(genChild);
-    }
-
-    function genChild(item: any, index: number) {
-      index += unref(getFirstToRenderRef);
-
-      const top = convertToUnit(index * unref(getItemHeightRef));
-      return (
-        <div class={`${prefixCls}__item`} style={{ top }} key={index}>
-          {getSlot(slots, 'default', { index, item })}
-        </div>
-      );
-    }
-
-    onMounted(() => {
-      state.last = getLast(0);
-      nextTick(() => {
-        const wrapEl = unref(wrapElRef);
-        if (!wrapEl) {
-          return;
-        }
-        useEventListener({
-          el: wrapEl,
-          name: 'scroll',
-          listener: onScroll,
-          wait: 0,
-        });
-      });
-    });
-    return () => (
-      <div class={prefixCls} style={unref(getWrapStyleRef)} ref={wrapElRef}>
-        <div class={`${prefixCls}__container`} style={unref(getContainerStyleRef)}>
-          {renderChildren()}
-        </div>
-      </div>
-    );
-  },
-});

+ 190 - 0
src/components/VirtualScroll/src/VirtualScroll.vue

@@ -0,0 +1,190 @@
+<script lang="tsx">
+  import {
+    defineComponent,
+    computed,
+    ref,
+    unref,
+    reactive,
+    onMounted,
+    watch,
+    nextTick,
+    CSSProperties,
+  } from 'vue';
+  import { useEventListener } from '/@/hooks/event/useEventListener';
+  import { getSlot } from '/@/utils/helper/tsxHelper';
+
+  type NumberOrNumberString = PropType<string | number | undefined>;
+
+  const props = {
+    height: [Number, String] as NumberOrNumberString,
+    maxHeight: [Number, String] as NumberOrNumberString,
+    maxWidth: [Number, String] as NumberOrNumberString,
+    minHeight: [Number, String] as NumberOrNumberString,
+    minWidth: [Number, String] as NumberOrNumberString,
+    width: [Number, String] as NumberOrNumberString,
+    bench: {
+      type: [Number, String] as NumberOrNumberString,
+      default: 0,
+    },
+    itemHeight: {
+      type: [Number, String] as NumberOrNumberString,
+      required: true,
+    },
+    items: {
+      type: Array as PropType<any[]>,
+      default: () => [],
+    },
+  };
+
+  const prefixCls = 'virtual-scroll';
+
+  function convertToUnit(str: string | number | null | undefined, unit = 'px'): string | undefined {
+    if (str == null || str === '') {
+      return undefined;
+    } else if (isNaN(+str!)) {
+      return String(str);
+    } else {
+      return `${Number(str)}${unit}`;
+    }
+  }
+
+  export default defineComponent({
+    name: 'VirtualScroll',
+    props,
+    setup(props, { slots }) {
+      const wrapElRef = ref<HTMLDivElement | null>(null);
+      const state = reactive({
+        first: 0,
+        last: 0,
+        scrollTop: 0,
+      });
+
+      const getBenchRef = computed(() => {
+        return parseInt(props.bench as string, 10);
+      });
+
+      const getItemHeightRef = computed(() => {
+        return parseInt(props.itemHeight as string, 10);
+      });
+
+      const getFirstToRenderRef = computed(() => {
+        return Math.max(0, state.first - unref(getBenchRef));
+      });
+
+      const getLastToRenderRef = computed(() => {
+        return Math.min((props.items || []).length, state.last + unref(getBenchRef));
+      });
+
+      const getContainerStyleRef = computed((): CSSProperties => {
+        return {
+          height: convertToUnit((props.items || []).length * unref(getItemHeightRef)),
+        };
+      });
+
+      const getWrapStyleRef = computed((): CSSProperties => {
+        const styles: Recordable<string> = {};
+        const height = convertToUnit(props.height);
+        const minHeight = convertToUnit(props.minHeight);
+        const minWidth = convertToUnit(props.minWidth);
+        const maxHeight = convertToUnit(props.maxHeight);
+        const maxWidth = convertToUnit(props.maxWidth);
+        const width = convertToUnit(props.width);
+
+        if (height) styles.height = height;
+        if (minHeight) styles.minHeight = minHeight;
+        if (minWidth) styles.minWidth = minWidth;
+        if (maxHeight) styles.maxHeight = maxHeight;
+        if (maxWidth) styles.maxWidth = maxWidth;
+        if (width) styles.width = width;
+        return styles;
+      });
+
+      watch([() => props.itemHeight, () => props.height], () => {
+        onScroll();
+      });
+
+      function getLast(first: number): number {
+        const wrapEl = unref(wrapElRef);
+        if (!wrapEl) {
+          return 0;
+        }
+        const height = parseInt(props.height || 0, 10) || wrapEl.clientHeight;
+
+        return first + Math.ceil(height / unref(getItemHeightRef));
+      }
+
+      function getFirst(): number {
+        return Math.floor(state.scrollTop / unref(getItemHeightRef));
+      }
+
+      function onScroll() {
+        const wrapEl = unref(wrapElRef);
+        if (!wrapEl) {
+          return;
+        }
+        state.scrollTop = wrapEl.scrollTop;
+        state.first = getFirst();
+        state.last = getLast(state.first);
+      }
+
+      function renderChildren() {
+        const { items = [] } = props;
+        return items.slice(unref(getFirstToRenderRef), unref(getLastToRenderRef)).map(genChild);
+      }
+
+      function genChild(item: any, index: number) {
+        index += unref(getFirstToRenderRef);
+        const top = convertToUnit(index * unref(getItemHeightRef));
+        return (
+          <div class={`${prefixCls}__item`} style={{ top }} key={index}>
+            {getSlot(slots, 'default', { index, item })}
+          </div>
+        );
+      }
+
+      onMounted(() => {
+        state.last = getLast(0);
+        nextTick(() => {
+          const wrapEl = unref(wrapElRef);
+          if (!wrapEl) {
+            return;
+          }
+          useEventListener({
+            el: wrapEl,
+            name: 'scroll',
+            listener: onScroll,
+            wait: 0,
+          });
+        });
+      });
+
+      return () => (
+        <div class={prefixCls} style={unref(getWrapStyleRef)} ref={wrapElRef}>
+          <div class={`${prefixCls}__container`} style={unref(getContainerStyleRef)}>
+            {renderChildren()}
+          </div>
+        </div>
+      );
+    },
+  });
+</script>
+<style scoped lang="less">
+  .virtual-scroll {
+    position: relative;
+    display: block;
+    width: 100%;
+    max-width: 100%;
+    overflow: auto;
+    flex: 1 1 auto;
+
+    &__container {
+      display: block;
+    }
+
+    &__item {
+      position: absolute;
+      right: 0;
+      left: 0;
+    }
+  }
+</style>

+ 0 - 18
src/components/VirtualScroll/src/index.less

@@ -1,18 +0,0 @@
-.virtual-scroll {
-  position: relative;
-  display: block;
-  width: 100%;
-  max-width: 100%;
-  overflow: auto;
-  flex: 1 1 auto;
-
-  &__container {
-    display: block;
-  }
-
-  &__item {
-    position: absolute;
-    right: 0;
-    left: 0;
-  }
-}

+ 0 - 27
src/components/VirtualScroll/src/props.ts

@@ -1,27 +0,0 @@
-// Helpers
-
-import type { PropType } from 'vue';
-// Types
-
-export type NumberOrNumberString = PropType<string | number | undefined>;
-
-export const props = {
-  height: [Number, String] as NumberOrNumberString,
-  maxHeight: [Number, String] as NumberOrNumberString,
-  maxWidth: [Number, String] as NumberOrNumberString,
-  minHeight: [Number, String] as NumberOrNumberString,
-  minWidth: [Number, String] as NumberOrNumberString,
-  width: [Number, String] as NumberOrNumberString,
-  bench: {
-    type: [Number, String] as NumberOrNumberString,
-    default: 0,
-  },
-  itemHeight: {
-    type: [Number, String] as NumberOrNumberString,
-    required: true,
-  },
-  items: {
-    type: Array as PropType<any[]>,
-    default: () => [],
-  },
-};

+ 1 - 1
src/components/registerGlobComp.ts

@@ -11,7 +11,7 @@ import { App } from 'vue';
 const compList = [Icon, AntButton.Group];
 
 export function registerGlobComp(app: App) {
-  compList.forEach((comp: any) => {
+  compList.forEach((comp) => {
     app.component(comp.name || comp.displayName, comp);
   });