提交 2c6aa852 编写于 作者: V Vben

refactor: code optimization

上级 0fe42a06
......@@ -7,6 +7,7 @@
### ✨ Refactor
- 重构项目以解决循环依赖项导致的热更新问题
- 移除 vueHelper/useClickoutside,使用@vueuse/core 代替
### 🐛 Bug Fixes
......
......@@ -135,6 +135,7 @@ If these plugins are helpful to you, you can give a star support
- [vite-plugin-theme](https://github.com/anncwb/vite-plugin-theme) - Used to pack compressed image resources
- [vite-plugin-imagemin](https://github.com/anncwb/vite-plugin-imagemin) - Used for online switching of theme colors and other color-related configurations
- [vite-plugin-compression](https://github.com/anncwb/vite-plugin-compression) - Used to pack input .gz|.brotil files
- [vite-plugin-svg-icons](https://github.com/anncwb/vite-plugin-svg-icons) - Used to quickly generate svg sprite
## Browser support
......
......@@ -135,6 +135,7 @@ yarn build
- [vite-plugin-theme](https://github.com/anncwb/vite-plugin-theme) - 用于打包压缩图片资源
- [vite-plugin-imagemin](https://github.com/anncwb/vite-plugin-imagemin) - 用于在线切换主题色等颜色相关配置
- [vite-plugin-compression](https://github.com/anncwb/vite-plugin-compression) - 用于打包输入.gz|.brotil 文件
- [vite-plugin-svg-icons](https://github.com/anncwb/vite-plugin-svg-icons) - 用于快速生成 svg 雪碧图
## 浏览器支持
......
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import AppLogo from './src/AppLogo.vue';
import AppProvider from './src/AppProvider.vue';
export const AppLocalePicker = createAsyncComponent(() => import('./src/AppLocalePicker.vue'));
export const AppSearch = createAsyncComponent(() => import('./src/search/AppSearch.vue'), {
loading: true,
});
import AppSearch from './src/search/AppSearch.vue';
import AppLocalePicker from './src/AppLocalePicker.vue';
export { useAppProviderContext } from './src/useAppContext';
export { AppLogo, AppProvider };
export { AppLogo, AppProvider, AppSearch, AppLocalePicker };
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import BasicArrow from './src/BasicArrow.vue';
import BasicTitle from './src/BasicTitle.vue';
import BasicHelp from './src/BasicHelp.vue';
export { BasicArrow, BasicTitle };
// export const BasicArrow = createAsyncComponent(() => import('./src/BasicArrow.vue'));
export const BasicHelp = createAsyncComponent(() => import('./src/BasicHelp.vue'));
// export const BasicTitle = createAsyncComponent(() => import('./src/BasicTitle.vue'));
export { BasicArrow, BasicTitle, BasicHelp };
......@@ -20,7 +20,6 @@
name: 'BasicArrow',
components: { Icon },
props: {
// Expand contract, expand by default
expand: propTypes.bool,
top: propTypes.bool,
bottom: propTypes.bool,
......
<script lang="tsx">
import type { CSSProperties, PropType } from 'vue';
import { defineComponent, computed, unref, h } from 'vue';
import { defineComponent, computed, unref } from 'vue';
import { Tooltip } from 'ant-design-vue';
import { InfoCircleOutlined } from '@ant-design/icons-vue';
......
......@@ -4,18 +4,16 @@
</div>
</template>
<script lang="ts">
import type { Ref } from 'vue';
import { defineComponent, ref, onMounted } from 'vue';
import { useClickOutside } from '/@/hooks/web/useClickOutside';
import { onClickOutside } from '@vueuse/core';
export default defineComponent({
name: 'ClickOutSide',
emits: ['mounted', 'clickOutside'],
setup(_, { emit }) {
const wrap = ref<ElRef>(null);
useClickOutside(wrap as Ref<HTMLDivElement>, () => {
onClickOutside(wrap, () => {
emit('clickOutside');
});
......
import { ref, unref } from 'vue';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { tryOnUnmounted } from '@vueuse/core';
export function useCountdown(count: number) {
const currentCount = ref(count);
......
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
// export const Description = createAsyncComponent(() => import('./src/index'));
import Description from './src/index.vue';
export { Description };
......
......@@ -19,7 +19,8 @@ import {
import { isProdMode } from '/@/utils/env';
import { isFunction } from '/@/utils/is';
import { tryOnUnmounted, isInSetup } from '/@/utils/helper/vueHelper';
import { tryOnUnmounted } from '@vueuse/core';
import { isEqual } from 'lodash-es';
import { error } from '/@/utils/log';
......@@ -31,8 +32,6 @@ const visibleData = reactive<{ [key: number]: boolean }>({});
* @description: Applicable to separate drawer and call outside
*/
export function useDrawer(): UseDrawerReturnType {
isInSetup();
const drawerRef = ref<DrawerInstance | null>(null);
const loadedRef = ref<Nullable<boolean>>(false);
const uidRef = ref<string>('');
......
......@@ -36,11 +36,7 @@ componentMap.set('AutoComplete', AutoComplete);
componentMap.set('Select', Select);
componentMap.set('ApiSelect', ApiSelect);
// componentMap.set('SelectOptGroup', Select.OptGroup);
// componentMap.set('SelectOption', Select.Option);
componentMap.set('TreeSelect', TreeSelect);
// componentMap.set('Transfer', Transfer);
// componentMap.set('Radio', Radio);
componentMap.set('Switch', Switch);
componentMap.set('RadioButtonGroup', RadioButtonGroup);
componentMap.set('RadioGroup', Radio.Group);
......
import type { ComponentType } from '../types/index';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { tryOnUnmounted } from '@vueuse/core';
import { add, del } from '../componentMap';
import type { Component } from 'vue';
......
import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
import { isInSetup } from '/@/utils/helper/vueHelper';
import { isProdMode } from '/@/utils/env';
import { error } from '/@/utils/log';
import { getDynamicProps } from '/@/utils';
......@@ -14,8 +13,6 @@ export declare type ValidateFields = (nameList?: NamePath[]) => Promise<Recordab
type Props = Partial<DynamicProps<FormProps>>;
export function useForm(props?: Props): UseFormReturnType {
isInSetup();
const formRef = ref<Nullable<FormActionType>>(null);
const loadedRef = ref<Nullable<boolean>>(false);
......
import Icon from './src/index.vue';
import SvgIcon from './src/SvgIcon.vue';
// import IconPicker from './src/IconPicker.vue';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
const IconPicker = createAsyncComponent(() => import('./src/IconPicker.vue'));
import IconPicker from './src/IconPicker.vue';
export { Icon, IconPicker, SvgIcon };
......
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
// export const Loading = createAsyncComponent(() => import('./src/index.vue'));
import Loading from './src/index.vue';
export { Loading };
......
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import BasicMenu from './src/BasicMenu.vue';
// export const BasicMenu = createAsyncComponent(() => import('./src/BasicMenu.vue'));
// export const MenuTag = createAsyncComponent(() => import('./src/components/MenuItemTag.vue'));
export { BasicMenu };
......@@ -38,7 +38,6 @@
import { getCurrentParentPath } from '/@/router/menus';
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
import { getAllParentPath } from '/@/router/helper/menuHelper';
......@@ -47,7 +46,6 @@
components: {
Menu,
BasicSubMenuItem,
// BasicSubMenuItem: createAsyncComponent(() => import('./components/BasicSubMenuItem.vue')),
},
props: basicProps,
emits: ['menuClick'],
......
......@@ -19,7 +19,8 @@ import {
import { isProdMode } from '/@/utils/env';
import { isFunction } from '/@/utils/is';
import { isEqual } from 'lodash-es';
import { tryOnUnmounted, isInSetup } from '/@/utils/helper/vueHelper';
import { tryOnUnmounted } from '@vueuse/core';
import { error } from '/@/utils/log';
import { computed } from 'vue';
const dataTransferRef = reactive<any>({});
......@@ -30,7 +31,6 @@ const visibleData = reactive<{ [key: number]: boolean }>({});
* @description: Applicable to independent modal and call outside
*/
export function useModal(): UseModalReturnType {
isInSetup();
const modalRef = ref<Nullable<ModalMethods>>(null);
const loadedRef = ref<Nullable<boolean>>(false);
const uidRef = ref<string>('');
......
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
// export const ImagePreview = createAsyncComponent(() => import('./src/index.vue'));
export { default as ImagePreview } from './src/index.vue';
......@@ -67,14 +67,14 @@
import { basicProps } from './props';
import expandIcon from './components/ExpandIcon';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import HeaderCell from './components/HeaderCell.vue';
import './style/index.less';
export default defineComponent({
components: {
Table,
BasicForm,
HeaderCell: createAsyncComponent(() => import('./components/HeaderCell.vue')),
HeaderCell,
},
props: basicProps,
emits: [
......
......@@ -10,14 +10,14 @@
import type { BasicColumn } from '../types/table';
import { defineComponent, computed } from 'vue';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import BasicHelp from '/@/components/Basic/src/BasicHelp.vue';
import EditTableHeaderCell from './EditTableHeaderIcon.vue';
import { useDesign } from '/@/hooks/web/useDesign';
export default defineComponent({
name: 'TableHeaderCell',
components: {
EditTableHeaderCell: createAsyncComponent(() => import('./EditTableHeaderIcon.vue')),
BasicHelp: createAsyncComponent(() => import('/@/components/Basic/src/BasicHelp.vue')),
EditTableHeaderCell,
BasicHelp,
},
props: {
column: {
......
......@@ -10,15 +10,17 @@
import { defineComponent, PropType, computed } from 'vue';
import type { TableSetting } from '../../types/table';
import { useI18n } from '/@/hooks/web/useI18n';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import ColumnSetting from './ColumnSetting.vue';
import SizeSetting from './SizeSetting.vue';
import RedoSetting from './RedoSetting.vue';
import FullScreenSetting from './FullScreenSetting.vue';
export default defineComponent({
name: 'TableSetting',
components: {
ColumnSetting,
SizeSetting: createAsyncComponent(() => import('./SizeSetting.vue')),
RedoSetting: createAsyncComponent(() => import('./RedoSetting.vue')),
FullScreenSetting: createAsyncComponent(() => import('./FullScreenSetting.vue')),
SizeSetting,
RedoSetting,
FullScreenSetting,
},
props: {
setting: {
......
......@@ -5,7 +5,6 @@ import { getDynamicProps } from '/@/utils';
import { ref, onUnmounted, unref, watch, toRaw } from 'vue';
import { isProdMode } from '/@/utils/env';
import { isInSetup } from '/@/utils/helper/vueHelper';
import { error } from '/@/utils/log';
import type { FormActionType } from '/@/components/Form';
......@@ -18,8 +17,6 @@ type UseTableMethod = TableActionType & {
export function useTable(
tableProps?: Props
): [(instance: TableActionType, formInstance: UseTableMethod) => void, TableActionType] {
isInSetup();
const tableRef = ref<Nullable<TableActionType>>(null);
const loadedRef = ref<Nullable<boolean>>(false);
const formRef = ref<Nullable<UseTableMethod>>(null);
......
......@@ -23,7 +23,7 @@ export function useTableScroll(
const modalFn = useModalContext();
// Greater than animation time 280
const [debounceRedoHeight] = useDebounce(redoHeight, 100);
const [debounceRedoHeight] = useDebounce(redoHeight, 200);
const getCanResize = computed(() => {
const { canResize, scroll } = unref(propsRef);
......@@ -31,7 +31,7 @@ export function useTableScroll(
});
watch(
() => [unref(getCanResize), , unref(getDataSourceRef)?.length],
() => [unref(getCanResize), unref(getDataSourceRef)?.length],
() => {
debounceRedoHeight();
},
......@@ -130,7 +130,6 @@ export function useTableScroll(
bodyEl!.style.height = `${height}px`;
}
useWindowSizeFn(calcTableHeight, 280);
onMountedOrActivated(() => {
calcTableHeight();
......
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
// export const BasicUpload = createAsyncComponent(() => import('./src/BasicUpload.vue'));
export { default as BasicUpload } from './src/BasicUpload.vue';
import { ref, watch } from 'vue';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { tryOnUnmounted } from '@vueuse/core';
import { isFunction } from '/@/utils/is';
export function useTimeoutFn(handle: Fn<any>, wait: number, native = false) {
......
import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { tryOnMounted, tryOnUnmounted } from '@vueuse/core';
import { useDebounce } from '/@/hooks/core/useDebounce';
interface WindowSizeOptions {
......
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { unref, Ref, nextTick } from 'vue';
import { tryOnUnmounted } from '@vueuse/core';
interface CallBackFn {
(instance: Nullable<ApexCharts>): void;
......
import { ref, Ref, unref } from 'vue';
import { useEventListener } from '/@/hooks/event/useEventListener';
import { isServer } from '/@/utils/is';
export function useClickOutside<T extends HTMLElement>(
containerRef: Ref<T>,
onClickOutside: (e: MouseEvent | TouchEvent) => void,
eventName = 'click'
) {
if (isServer) return;
const isTouchRef = ref(false);
useEventListener({
el: document,
name: 'touchend',
listener: handler,
options: true,
});
useEventListener({
el: document,
name: eventName,
listener: handler,
options: true,
});
function handler(e: MouseEvent | TouchEvent) {
if (e.type === 'touchend') {
isTouchRef.value = true;
}
if (e.type === 'click' && unref(isTouchRef)) return;
const el = containerRef.value;
if (el && e.target && !el.contains(e.target as Node)) {
onClickOutside(e);
}
}
}
import { useTimeoutFn } from '/@/hooks/core/useTimeout';
import { tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { tryOnUnmounted } from '@vueuse/core';
import { unref, Ref, nextTick } from 'vue';
import type { EChartsOption } from 'echarts';
import { useDebounce } from '/@/hooks/core/useDebounce';
......
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import FullScreen from './FullScreen.vue';
export const UserDropDown = createAsyncComponent(() => import('./user-dropdown/index.vue'), {
loading: true,
......@@ -6,8 +7,8 @@ export const UserDropDown = createAsyncComponent(() => import('./user-dropdown/i
export const LayoutBreadcrumb = createAsyncComponent(() => import('./Breadcrumb.vue'));
export const FullScreen = createAsyncComponent(() => import('./FullScreen.vue'));
export const Notify = createAsyncComponent(() => import('./notify/index.vue'));
export const ErrorAction = createAsyncComponent(() => import('./ErrorAction.vue'));
export { FullScreen };
......@@ -31,6 +31,9 @@
import { Tabs } from 'ant-design-vue';
import TabContent from './components/TabContent.vue';
import QuickButton from './components/QuickButton.vue';
import FoldButton from './components/FoldButton.vue';
import TabRedo from './components/TabRedo.vue';
import type { RouteLocationNormalized } from 'vue-router';
import { useGo } from '/@/hooks/web/usePage';
......@@ -39,20 +42,20 @@
import { userStore } from '/@/store/modules/user';
import { initAffixTabs, useTabsDrag } from './useMultipleTabs';
import { REDIRECT_NAME } from '/@/router/constant';
import { useDesign } from '/@/hooks/web/useDesign';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
import { REDIRECT_NAME } from '/@/router/constant';
import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
import router from '/@/router';
export default defineComponent({
name: 'MultipleTabs',
components: {
QuickButton: createAsyncComponent(() => import('./components/QuickButton.vue')),
TabRedo: createAsyncComponent(() => import('./components/TabRedo.vue')),
FoldButton: createAsyncComponent(() => import('./components/FoldButton.vue')),
QuickButton,
TabRedo: TabRedo,
FoldButton,
Tabs,
TabPane: Tabs.TabPane,
TabContent,
......
import type { FunctionalComponent } from 'vue';
import type { RouteLocation } from 'vue-router';
import { computed, ref, unref } from 'vue';
import { computed, ref, unref, getCurrentInstance } from 'vue';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { tryTsxEmit } from '/@/utils/helper/vueHelper';
import { useRouter } from 'vue-router';
import { useStore } from 'vuex';
......@@ -20,21 +19,19 @@ export function useCache(isPage: boolean) {
const name = ref('');
const { currentRoute } = useRouter();
tryTsxEmit((instance) => {
const routeName = instance.type.name;
if (routeName && ![ParentLayoutName].includes(routeName)) {
name.value = routeName;
} else {
const matched = currentRoute.value?.matched;
if (!matched) {
return;
}
const len = matched.length;
if (len < 2) return;
name.value = matched[len - 2].name as string;
const instance = getCurrentInstance();
const routeName = instance?.type.name;
if (routeName && ![ParentLayoutName].includes(routeName)) {
name.value = routeName;
} else {
const matched = currentRoute.value?.matched;
if (!matched) {
return;
}
});
const len = matched.length;
if (len < 2) return;
name.value = matched[len - 2].name as string;
}
const { getOpenKeepAlive } = useRootSetting();
......
......@@ -33,14 +33,3 @@ export function extendSlots(slots: Slots, excludeKeys: string[] = []) {
});
return ret;
}
// Get events on attrs
export function getListeners(attrs: Recordable<unknown>) {
const listeners: any = {};
Object.keys(attrs).forEach((key) => {
if (/^on/.test(key)) {
listeners[key] = attrs[key];
}
});
return listeners;
}
import {
watch,
computed,
WatchSource,
getCurrentInstance,
onMounted,
onUnmounted,
nextTick,
reactive,
ComponentInternalInstance,
} from 'vue';
import { error } from '../log';
export function explicitComputed<T, S>(source: WatchSource<S>, fn: () => T) {
const v = reactive<any>({ value: fn() });
watch(source, () => (v.value = fn()));
return computed<T>(() => v.value);
}
export function tryOnMounted(fn: () => void, sync = true) {
if (getCurrentInstance()) {
onMounted(fn);
} else if (sync) {
fn();
} else {
nextTick(fn);
}
}
export function tryOnUnmounted(fn: () => Promise<void> | void) {
getCurrentInstance() && onUnmounted(fn);
}
export function tryTsxEmit<T extends any = ComponentInternalInstance>(
fn: (_instance: T) => Promise<void> | void
) {
const instance = getCurrentInstance() as any;
instance && fn.call(null, instance);
}
export function isInSetup() {
if (!getCurrentInstance()) {
error('Please put useForm function in the setup function!');
}
}
import { dateUtil } from '/@/utils/dateUtil';
import { reactive, toRefs } from 'vue';
import { tryOnMounted, tryOnUnmounted } from '/@/utils/helper/vueHelper';
import { localeStore } from '/@/store/modules/locale';
import { tryOnMounted, tryOnUnmounted } from '@vueuse/core';
export function useNow(immediate = true) {
const localData = dateUtil.localeData(localeStore.getLocale);
......
......@@ -7126,10 +7126,10 @@ postcss@^8.1.10, postcss@^8.2.1:
nanoid "^3.1.20"
source-map "^0.6.1"
postcss@^8.2.7:
version "8.2.7"
resolved "https://registry.npmjs.org/postcss/-/postcss-8.2.7.tgz#48ed8d88b4de10afa0dfd1c3f840aa57b55c4d47"
integrity sha512-DsVLH3xJzut+VT+rYr0mtvOtpTjSyqDwPf5EZWXcb0uAKfitGpTY9Ec+afi2+TgdN8rWS9Cs88UDYehKo/RvOw==
postcss@^8.2.8:
version "8.2.8"
resolved "https://registry.npmjs.org/postcss/-/postcss-8.2.8.tgz#0b90f9382efda424c4f0f69a2ead6f6830d08ece"
integrity sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw==
dependencies:
colorette "^1.2.2"
nanoid "^3.1.20"
......@@ -9113,10 +9113,10 @@ vite-plugin-imagemin@^0.2.9:
imagemin-svgo "^8.0.0"
imagemin-webp "^6.0.0"
vite-plugin-mock@^2.2.2:
version "2.2.2"
resolved "https://registry.npmjs.org/vite-plugin-mock/-/vite-plugin-mock-2.2.2.tgz#94c5aa6851c82f30417e9dd0feedf809e9ff6265"
integrity sha512-2qqQvjQHS2ENxdyNqHlUKdo4hx7EDAlZ3CW+sUKmjZi/3ItvMJdSbKvIkiM/aBb3MEI450iAdxLOPubikDkGhQ==
vite-plugin-mock@^2.2.3:
version "2.2.3"
resolved "https://registry.npmjs.org/vite-plugin-mock/-/vite-plugin-mock-2.2.3.tgz#b2194ca4346933d9d9f0ec39ea1c4c1ea3c744f2"
integrity sha512-xbHo2k2fENJu6Y5eOCxZiZovUgSIRL0efgdhWb9rRjF8k+MHRWbtXgMufRWFtthgZCfz1m3U4uV4TIA4IO/8eQ==
dependencies:
"@rollup/plugin-node-resolve" "^11.2.0"
"@types/mockjs" "^1.0.3"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册