fix: hmr error fixed

修复部分组件可能会造成热更新异常的问题
This commit is contained in:
无木 2021-09-18 14:58:22 +08:00
parent 9c5f11a54b
commit 5af452754b
3 changed files with 133 additions and 158 deletions

View File

@ -16,7 +16,9 @@
- 修复点击关闭按钮、最大化按钮旁边的空白区域也会导致`Modal`关闭的问题 - 修复点击关闭按钮、最大化按钮旁边的空白区域也会导致`Modal`关闭的问题
- **BasicTree** 修复节点插槽不起作用的问题 - **BasicTree** 修复节点插槽不起作用的问题
- **CodeEditor** 修复可能会造成的`Build`失败的问题 - **CodeEditor** 修复可能会造成的`Build`失败的问题
- **其它** 修复多标签在某些情况下关闭页签不会跳转路由的问题 - **其它**
- 修复多标签在某些情况下关闭页签不会跳转路由的问题
- 修复部分组件可能会造成热更新异常的问题
## 2.7.2(2021-09-14) ## 2.7.2(2021-09-14)

View File

@ -1,17 +1,17 @@
<template> <template>
<Dropdown :trigger="trigger" v-bind="$attrs"> <a-dropdown :trigger="trigger" v-bind="$attrs">
<span> <span>
<slot></slot> <slot></slot>
</span> </span>
<template #overlay> <template #overlay>
<Menu :selectedKeys="selectedKeys"> <a-menu :selectedKeys="selectedKeys">
<template v-for="item in dropMenuList" :key="`${item.event}`"> <template v-for="item in dropMenuList" :key="`${item.event}`">
<MenuItem <a-menu-item
v-bind="getAttr(item.event)" v-bind="getAttr(item.event)"
@click="handleClickMenu(item)" @click="handleClickMenu(item)"
:disabled="item.disabled" :disabled="item.disabled"
> >
<Popconfirm <a-popconfirm
v-if="popconfirm && item.popConfirm" v-if="popconfirm && item.popConfirm"
v-bind="getPopConfirmAttrs(item.popConfirm)" v-bind="getPopConfirmAttrs(item.popConfirm)"
> >
@ -22,86 +22,73 @@
<Icon :icon="item.icon" v-if="item.icon" /> <Icon :icon="item.icon" v-if="item.icon" />
<span class="ml-1">{{ item.text }}</span> <span class="ml-1">{{ item.text }}</span>
</div> </div>
</Popconfirm> </a-popconfirm>
<template v-else> <template v-else>
<Icon :icon="item.icon" v-if="item.icon" /> <Icon :icon="item.icon" v-if="item.icon" />
<span class="ml-1">{{ item.text }}</span> <span class="ml-1">{{ item.text }}</span>
</template> </template>
</MenuItem> </a-menu-item>
<MenuDivider v-if="item.divider" :key="`d-${item.event}`" /> <a-menu-divider v-if="item.divider" :key="`d-${item.event}`" />
</template> </template>
</Menu> </a-menu>
</template> </template>
</Dropdown> </a-dropdown>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { computed, PropType } from 'vue'; import { computed, PropType } from 'vue';
import type { DropMenu } from './typing'; import type { DropMenu } from './typing';
import { defineComponent } from 'vue';
import { Dropdown, Menu, Popconfirm } from 'ant-design-vue'; import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
import { Icon } from '/@/components/Icon'; import { Icon } from '/@/components/Icon';
import { omit } from 'lodash-es'; import { omit } from 'lodash-es';
import { isFunction } from '/@/utils/is'; import { isFunction } from '/@/utils/is';
export default defineComponent({ const ADropdown = Dropdown;
name: 'BasicDropdown', const AMenu = Menu;
components: { const AMenuItem = Menu.Item;
Dropdown, const AMenuDivider = Menu.Divider;
Menu, const APopconfirm = Popconfirm;
MenuItem: Menu.Item,
MenuDivider: Menu.Divider, const props = defineProps({
Icon, popconfirm: Boolean,
Popconfirm, /**
}, * the trigger mode which executes the drop-down action
props: { * @default ['hover']
popconfirm: Boolean, * @type string[]
/** */
* the trigger mode which executes the drop-down action trigger: {
* @default ['hover'] type: [Array] as PropType<('contextmenu' | 'click' | 'hover')[]>,
* @type string[] default: () => {
*/ return ['contextmenu'];
trigger: {
type: [Array] as PropType<('contextmenu' | 'click' | 'hover')[]>,
default: () => {
return ['contextmenu'];
},
},
dropMenuList: {
type: Array as PropType<(DropMenu & Recordable)[]>,
default: () => [],
},
selectedKeys: {
type: Array as PropType<string[]>,
default: () => [],
}, },
}, },
emits: ['menuEvent'], dropMenuList: {
setup(props, { emit }) { type: Array as PropType<(DropMenu & Recordable)[]>,
function handleClickMenu(item: DropMenu) { default: () => [],
const { event } = item; },
const menu = props.dropMenuList.find((item) => `${item.event}` === `${event}`); selectedKeys: {
emit('menuEvent', menu); type: Array as PropType<string[]>,
item.onClick?.(); default: () => [],
}
const getPopConfirmAttrs = computed(() => {
return (attrs) => {
const originAttrs = omit(attrs, ['confirm', 'cancel', 'icon']);
if (!attrs.onConfirm && attrs.confirm && isFunction(attrs.confirm))
originAttrs['onConfirm'] = attrs.confirm;
if (!attrs.onCancel && attrs.cancel && isFunction(attrs.cancel))
originAttrs['onCancel'] = attrs.cancel;
return originAttrs;
};
});
return {
handleClickMenu,
getPopConfirmAttrs,
getAttr: (key: string | number) => ({ key }),
};
}, },
}); });
const emit = defineEmits(['menuEvent']);
function handleClickMenu(item: DropMenu) {
const { event } = item;
const menu = props.dropMenuList.find((item) => `${item.event}` === `${event}`);
emit('menuEvent', menu);
item.onClick?.();
}
const getPopConfirmAttrs = computed(() => {
return (attrs) => {
const originAttrs = omit(attrs, ['confirm', 'cancel', 'icon']);
if (!attrs.onConfirm && attrs.confirm && isFunction(attrs.confirm))
originAttrs['onConfirm'] = attrs.confirm;
if (!attrs.onCancel && attrs.cancel && isFunction(attrs.cancel))
originAttrs['onCancel'] = attrs.cancel;
return originAttrs;
};
});
</script> </script>

View File

@ -7,7 +7,7 @@
v-model:value="currentSelect" v-model:value="currentSelect"
> >
<template #addonAfter> <template #addonAfter>
<Popover <a-popover
placement="bottomLeft" placement="bottomLeft"
trigger="click" trigger="click"
v-model="visible" v-model="visible"
@ -17,7 +17,7 @@
<div class="flex justify-between"> <div class="flex justify-between">
<a-input <a-input
:placeholder="t('component.icon.search')" :placeholder="t('component.icon.search')"
@change="handleSearchChange" @change="debounceHandleSearchChange"
allowClear allowClear
/> />
</div> </div>
@ -53,7 +53,7 @@
</ul> </ul>
</ScrollContainer> </ScrollContainer>
<div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize"> <div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize">
<Pagination <a-pagination
showLessItems showLessItems
size="small" size="small"
:pageSize="pageSize" :pageSize="pageSize"
@ -63,7 +63,7 @@
</div> </div>
</div> </div>
<template v-else <template v-else
><div class="p-5"><Empty /></div> ><div class="p-5"><a-empty /></div>
</template> </template>
</template> </template>
@ -71,16 +71,14 @@
<SvgIcon :name="currentSelect" /> <SvgIcon :name="currentSelect" />
</span> </span>
<Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else /> <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else />
</Popover> </a-popover>
</template> </template>
</a-input> </a-input>
</template> </template>
<script lang="ts"> <script lang="ts" setup>
import { defineComponent, ref, watchEffect, watch, unref } from 'vue'; import { ref, watchEffect, watch, unref } from 'vue';
import { useDesign } from '/@/hooks/web/useDesign'; import { useDesign } from '/@/hooks/web/useDesign';
import { ScrollContainer } from '/@/components/Container'; import { ScrollContainer } from '/@/components/Container';
import { Input, Popover, Pagination, Empty } from 'ant-design-vue'; import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
import Icon from './Icon.vue'; import Icon from './Icon.vue';
import SvgIcon from './SvgIcon.vue'; import SvgIcon from './SvgIcon.vue';
@ -94,6 +92,12 @@
import { useMessage } from '/@/hooks/web/useMessage'; import { useMessage } from '/@/hooks/web/useMessage';
import svgIcons from 'virtual:svg-icons-names'; import svgIcons from 'virtual:svg-icons-names';
// 使WebStormunused
const AInput = Input;
const APopover = Popover;
const APagination = Pagination;
const AEmpty = Empty;
function getIcons() { function getIcons() {
const data = iconsData as any; const data = iconsData as any;
const prefix: string = data?.prefix ?? ''; const prefix: string = data?.prefix ?? '';
@ -110,88 +114,70 @@
return svgIcons.map((icon) => icon.replace('icon-', '')); return svgIcons.map((icon) => icon.replace('icon-', ''));
} }
export default defineComponent({ const props = defineProps({
name: 'IconPicker', value: propTypes.string,
components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty, SvgIcon }, width: propTypes.string.def('100%'),
inheritAttrs: false, pageSize: propTypes.number.def(140),
props: { copy: propTypes.bool.def(false),
value: propTypes.string, mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
width: propTypes.string.def('100%'),
pageSize: propTypes.number.def(140),
copy: propTypes.bool.def(false),
mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
},
emits: ['change', 'update:value'],
setup(props, { emit }) {
const isSvgMode = props.mode === 'svg';
const icons = isSvgMode ? getSvgIcons() : getIcons();
const currentSelect = ref('');
const visible = ref(false);
const currentList = ref(icons);
const { t } = useI18n();
const { prefixCls } = useDesign('icon-picker');
const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);
const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
const { createMessage } = useMessage();
const { getPaginationList, getTotal, setCurrentPage } = usePagination(
currentList,
props.pageSize,
);
watchEffect(() => {
currentSelect.value = props.value;
});
watch(
() => currentSelect.value,
(v) => {
emit('update:value', v);
return emit('change', v);
},
);
function handlePageChange(page: number) {
setCurrentPage(page);
}
function handleClick(icon: string) {
currentSelect.value = icon;
if (props.copy) {
clipboardRef.value = icon;
if (unref(isSuccessRef)) {
createMessage.success(t('component.icon.copy'));
}
}
}
function handleSearchChange(e: ChangeEvent) {
const value = e.target.value;
if (!value) {
setCurrentPage(1);
currentList.value = icons;
return;
}
currentList.value = icons.filter((item) => item.includes(value));
}
return {
t,
prefixCls,
visible,
isSvgMode,
getTotal,
getPaginationList,
handlePageChange,
handleClick,
currentSelect,
handleSearchChange: debounceHandleSearchChange,
};
},
}); });
const emit = defineEmits(['change', 'update:value']);
const isSvgMode = props.mode === 'svg';
const icons = isSvgMode ? getSvgIcons() : getIcons();
const currentSelect = ref('');
const visible = ref(false);
const currentList = ref(icons);
const { t } = useI18n();
const { prefixCls } = useDesign('icon-picker');
const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);
const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
const { createMessage } = useMessage();
const { getPaginationList, getTotal, setCurrentPage } = usePagination(
currentList,
props.pageSize,
);
watchEffect(() => {
currentSelect.value = props.value;
});
watch(
() => currentSelect.value,
(v) => {
emit('update:value', v);
return emit('change', v);
},
);
function handlePageChange(page: number) {
setCurrentPage(page);
}
function handleClick(icon: string) {
currentSelect.value = icon;
if (props.copy) {
clipboardRef.value = icon;
if (unref(isSuccessRef)) {
createMessage.success(t('component.icon.copy'));
}
}
}
function handleSearchChange(e: ChangeEvent) {
const value = e.target.value;
if (!value) {
setCurrentPage(1);
currentList.value = icons;
return;
}
currentList.value = icons.filter((item) => item.includes(value));
}
</script> </script>
<style lang="less"> <style lang="less">
@prefix-cls: ~'@{namespace}-icon-picker'; @prefix-cls: ~'@{namespace}-icon-picker';