提交 3b2c40be 作者: Vben

refactor(virtual-scroll): refactor virtualScroll component

上级 1c1755cf
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { withInstall } from '/@/utils';
export const MarkDown = createAsyncComponent(() => import('./src/Markdown.vue')); import markDown from './src/Markdown.vue';
export * from './src/types'; export const MarkDown = withInstall(markDown);
export * from './src/typing';
...@@ -14,18 +14,17 @@ ...@@ -14,18 +14,17 @@
} from 'vue'; } from 'vue';
import Vditor from 'vditor'; import Vditor from 'vditor';
import 'vditor/dist/index.css'; import 'vditor/dist/index.css';
import { propTypes } from '/@/utils/propTypes';
import { useLocale } from '/@/locales/useLocale'; import { useLocale } from '/@/locales/useLocale';
import { useModalContext } from '../../Modal'; import { useModalContext } from '../../Modal';
import { useRootSetting } from '/@/hooks/setting/useRootSetting'; import { useRootSetting } from '/@/hooks/setting/useRootSetting';
type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined; type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
export default defineComponent({ export default defineComponent({
inheritAttrs: false, inheritAttrs: false,
props: { props: {
height: propTypes.number.def(360), height: { type: Number, default: 360 },
value: propTypes.string.def(''), value: { type: String, default: '' },
}, },
emits: ['change', 'get'], emits: ['change', 'get'],
setup(props, { attrs, emit }) { setup(props, { attrs, emit }) {
......
export { default as StrengthMeter } from './src/StrengthMeter.vue'; import { withInstall } from '/@/utils';
import strengthMeter from './src/StrengthMeter.vue';
export const StrengthMeter = withInstall(strengthMeter);
...@@ -20,10 +20,7 @@ ...@@ -20,10 +20,7 @@
<script lang="ts"> <script lang="ts">
import { defineComponent, computed, ref, watch, unref, watchEffect } from 'vue'; import { defineComponent, computed, ref, watch, unref, watchEffect } from 'vue';
import { Input } from 'ant-design-vue'; import { Input } from 'ant-design-vue';
// @ts-ignore
import { zxcvbn } from '@zxcvbn-ts/core'; import { zxcvbn } from '@zxcvbn-ts/core';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
......
export { default as Time } from './src/Time.vue'; import { withInstall } from '/@/utils/index';
import time from './src/Time.vue';
export const Time = withInstall(time);
...@@ -3,10 +3,8 @@ ...@@ -3,10 +3,8 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, ref, watch } from 'vue'; import { defineComponent, ref, watch } from 'vue';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { useIntervalFn } from '@vueuse/core'; import { useIntervalFn } from '@vueuse/core';
import { formatToDateTime, formatToDate, dateUtil } from '/@/utils/dateUtil'; import { formatToDateTime, formatToDate, dateUtil } from '/@/utils/dateUtil';
import { isNumber, isObject, isString } from '/@/utils/is'; import { isNumber, isObject, isString } from '/@/utils/is';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
...@@ -15,6 +13,7 @@ ...@@ -15,6 +13,7 @@
const ONE_MINUTES = ONE_SECONDS * 60; const ONE_MINUTES = ONE_SECONDS * 60;
const ONE_HOUR = ONE_MINUTES * 60; const ONE_HOUR = ONE_MINUTES * 60;
const ONE_DAY = ONE_HOUR * 24; const ONE_DAY = ONE_HOUR * 24;
export default defineComponent({ export default defineComponent({
name: 'Time', name: 'Time',
props: { props: {
......
import Tinymce from './src/Editor.vue'; import { withInstall } from '/@/utils/index';
export { Tinymce }; import tinymce from './src/Editor.vue';
export const Tinymce = withInstall(tinymce);
...@@ -16,7 +16,6 @@ ...@@ -16,7 +16,6 @@
import type { RawEditorSettings } from 'tinymce'; import type { RawEditorSettings } from 'tinymce';
import tinymce from 'tinymce/tinymce'; import tinymce from 'tinymce/tinymce';
import 'tinymce/themes/silver'; import 'tinymce/themes/silver';
import 'tinymce/icons/default/icons'; import 'tinymce/icons/default/icons';
import 'tinymce/plugins/advlist'; import 'tinymce/plugins/advlist';
import 'tinymce/plugins/anchor'; import 'tinymce/plugins/anchor';
...@@ -58,11 +57,8 @@ ...@@ -58,11 +57,8 @@
onUnmounted, onUnmounted,
onDeactivated, onDeactivated,
} from 'vue'; } from 'vue';
import ImgUpload from './ImgUpload.vue'; import ImgUpload from './ImgUpload.vue';
import { toolbar, plugins } from './tinymce'; import { toolbar, plugins } from './tinymce';
import { buildShortUUID } from '/@/utils/uuid'; import { buildShortUUID } from '/@/utils/uuid';
import { bindHandlers } from './helper'; import { bindHandlers } from './helper';
import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated'; import { onMountedOrActivated } from '/@/hooks/core/onMountedOrActivated';
...@@ -96,7 +92,6 @@ ...@@ -96,7 +92,6 @@
required: false, required: false,
default: 400, default: 400,
}, },
width: { width: {
type: [Number, String] as PropType<string | number>, type: [Number, String] as PropType<string | number>,
required: false, required: false,
......
...@@ -52,9 +52,9 @@ ...@@ -52,9 +52,9 @@
function handleChange(info: Recordable) { function handleChange(info: Recordable) {
const file = info.file; const file = info.file;
const status = file?.status; const status = file?.status;
const url = file?.response?.url; const url = file?.response?.url;
const name = file?.name; const name = file?.name;
if (status === 'uploading') { if (status === 'uploading') {
if (!uploading) { if (!uploading) {
emit('uploading', name); emit('uploading', name);
......
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);
import { <script lang="tsx">
import {
defineComponent, defineComponent,
computed, computed,
ref, ref,
...@@ -8,16 +9,36 @@ import { ...@@ -8,16 +9,36 @@ import {
watch, watch,
nextTick, nextTick,
CSSProperties, CSSProperties,
} from 'vue'; } from 'vue';
import { useEventListener } from '/@/hooks/event/useEventListener'; import { useEventListener } from '/@/hooks/event/useEventListener';
import { getSlot } from '/@/utils/helper/tsxHelper';
import { props as basicProps } from './props';
import { getSlot } from '/@/utils/helper/tsxHelper'; type NumberOrNumberString = PropType<string | number | undefined>;
import './index.less';
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'; const prefixCls = 'virtual-scroll';
function convertToUnit(str: string | number | null | undefined, unit = 'px'): string | undefined { function convertToUnit(str: string | number | null | undefined, unit = 'px'): string | undefined {
if (str == null || str === '') { if (str == null || str === '') {
return undefined; return undefined;
} else if (isNaN(+str!)) { } else if (isNaN(+str!)) {
...@@ -25,11 +46,11 @@ function convertToUnit(str: string | number | null | undefined, unit = 'px'): st ...@@ -25,11 +46,11 @@ function convertToUnit(str: string | number | null | undefined, unit = 'px'): st
} else { } else {
return `${Number(str)}${unit}`; return `${Number(str)}${unit}`;
} }
} }
export default defineComponent({ export default defineComponent({
name: 'VirtualScroll', name: 'VirtualScroll',
props: basicProps, props,
setup(props, { slots }) { setup(props, { slots }) {
const wrapElRef = ref<HTMLDivElement | null>(null); const wrapElRef = ref<HTMLDivElement | null>(null);
const state = reactive({ const state = reactive({
...@@ -113,7 +134,6 @@ export default defineComponent({ ...@@ -113,7 +134,6 @@ export default defineComponent({
function genChild(item: any, index: number) { function genChild(item: any, index: number) {
index += unref(getFirstToRenderRef); index += unref(getFirstToRenderRef);
const top = convertToUnit(index * unref(getItemHeightRef)); const top = convertToUnit(index * unref(getItemHeightRef));
return ( return (
<div class={`${prefixCls}__item`} style={{ top }} key={index}> <div class={`${prefixCls}__item`} style={{ top }} key={index}>
...@@ -137,6 +157,7 @@ export default defineComponent({ ...@@ -137,6 +157,7 @@ export default defineComponent({
}); });
}); });
}); });
return () => ( return () => (
<div class={prefixCls} style={unref(getWrapStyleRef)} ref={wrapElRef}> <div class={prefixCls} style={unref(getWrapStyleRef)} ref={wrapElRef}>
<div class={`${prefixCls}__container`} style={unref(getContainerStyleRef)}> <div class={`${prefixCls}__container`} style={unref(getContainerStyleRef)}>
...@@ -145,4 +166,25 @@ export default defineComponent({ ...@@ -145,4 +166,25 @@ export default defineComponent({
</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>
.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;
}
}
// 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: () => [],
},
};
...@@ -11,7 +11,7 @@ import { App } from 'vue'; ...@@ -11,7 +11,7 @@ import { App } from 'vue';
const compList = [Icon, AntButton.Group]; const compList = [Icon, AntButton.Group];
export function registerGlobComp(app: App) { export function registerGlobComp(app: App) {
compList.forEach((comp: any) => { compList.forEach((comp) => {
app.component(comp.name || comp.displayName, comp); app.component(comp.name || comp.displayName, comp);
}); });
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论