Commit 5af452754b0567539e6ba6899ce91fa2914a4829

Authored by 无木
1 parent 9c5f11a5

fix: hmr error fixed

修复部分组件可能会造成热更新异常的问题
CHANGELOG.zh_CN.md
@@ -16,7 +16,9 @@ @@ -16,7 +16,9 @@
16 - 修复点击关闭按钮、最大化按钮旁边的空白区域也会导致`Modal`关闭的问题 16 - 修复点击关闭按钮、最大化按钮旁边的空白区域也会导致`Modal`关闭的问题
17 - **BasicTree** 修复节点插槽不起作用的问题 17 - **BasicTree** 修复节点插槽不起作用的问题
18 - **CodeEditor** 修复可能会造成的`Build`失败的问题 18 - **CodeEditor** 修复可能会造成的`Build`失败的问题
19 -- **其它** 修复多标签在某些情况下关闭页签不会跳转路由的问题 19 +- **其它**
  20 + - 修复多标签在某些情况下关闭页签不会跳转路由的问题
  21 + - 修复部分组件可能会造成热更新异常的问题
20 22
21 ## 2.7.2(2021-09-14) 23 ## 2.7.2(2021-09-14)
22 24
src/components/Dropdown/src/Dropdown.vue
1 <template> 1 <template>
2 - <Dropdown :trigger="trigger" v-bind="$attrs"> 2 + <a-dropdown :trigger="trigger" v-bind="$attrs">
3 <span> 3 <span>
4 <slot></slot> 4 <slot></slot>
5 </span> 5 </span>
6 <template #overlay> 6 <template #overlay>
7 - <Menu :selectedKeys="selectedKeys"> 7 + <a-menu :selectedKeys="selectedKeys">
8 <template v-for="item in dropMenuList" :key="`${item.event}`"> 8 <template v-for="item in dropMenuList" :key="`${item.event}`">
9 - <MenuItem 9 + <a-menu-item
10 v-bind="getAttr(item.event)" 10 v-bind="getAttr(item.event)"
11 @click="handleClickMenu(item)" 11 @click="handleClickMenu(item)"
12 :disabled="item.disabled" 12 :disabled="item.disabled"
13 > 13 >
14 - <Popconfirm 14 + <a-popconfirm
15 v-if="popconfirm && item.popConfirm" 15 v-if="popconfirm && item.popConfirm"
16 v-bind="getPopConfirmAttrs(item.popConfirm)" 16 v-bind="getPopConfirmAttrs(item.popConfirm)"
17 > 17 >
@@ -22,86 +22,73 @@ @@ -22,86 +22,73 @@
22 <Icon :icon="item.icon" v-if="item.icon" /> 22 <Icon :icon="item.icon" v-if="item.icon" />
23 <span class="ml-1">{{ item.text }}</span> 23 <span class="ml-1">{{ item.text }}</span>
24 </div> 24 </div>
25 - </Popconfirm> 25 + </a-popconfirm>
26 <template v-else> 26 <template v-else>
27 <Icon :icon="item.icon" v-if="item.icon" /> 27 <Icon :icon="item.icon" v-if="item.icon" />
28 <span class="ml-1">{{ item.text }}</span> 28 <span class="ml-1">{{ item.text }}</span>
29 </template> 29 </template>
30 - </MenuItem>  
31 - <MenuDivider v-if="item.divider" :key="`d-${item.event}`" /> 30 + </a-menu-item>
  31 + <a-menu-divider v-if="item.divider" :key="`d-${item.event}`" />
32 </template> 32 </template>
33 - </Menu> 33 + </a-menu>
34 </template> 34 </template>
35 - </Dropdown> 35 + </a-dropdown>
36 </template> 36 </template>
37 37
38 -<script lang="ts"> 38 +<script lang="ts" setup>
39 import { computed, PropType } from 'vue'; 39 import { computed, PropType } from 'vue';
40 import type { DropMenu } from './typing'; 40 import type { DropMenu } from './typing';
41 -  
42 - import { defineComponent } from 'vue';  
43 import { Dropdown, Menu, Popconfirm } from 'ant-design-vue'; 41 import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
44 import { Icon } from '/@/components/Icon'; 42 import { Icon } from '/@/components/Icon';
45 import { omit } from 'lodash-es'; 43 import { omit } from 'lodash-es';
46 import { isFunction } from '/@/utils/is'; 44 import { isFunction } from '/@/utils/is';
47 45
48 - export default defineComponent({  
49 - name: 'BasicDropdown',  
50 - components: {  
51 - Dropdown,  
52 - Menu,  
53 - MenuItem: Menu.Item,  
54 - MenuDivider: Menu.Divider,  
55 - Icon,  
56 - Popconfirm,  
57 - },  
58 - props: {  
59 - popconfirm: Boolean,  
60 - /**  
61 - * the trigger mode which executes the drop-down action  
62 - * @default ['hover']  
63 - * @type string[]  
64 - */  
65 - trigger: {  
66 - type: [Array] as PropType<('contextmenu' | 'click' | 'hover')[]>,  
67 - default: () => {  
68 - return ['contextmenu'];  
69 - },  
70 - },  
71 - dropMenuList: {  
72 - type: Array as PropType<(DropMenu & Recordable)[]>,  
73 - default: () => [],  
74 - },  
75 - selectedKeys: {  
76 - type: Array as PropType<string[]>,  
77 - default: () => [], 46 + const ADropdown = Dropdown;
  47 + const AMenu = Menu;
  48 + const AMenuItem = Menu.Item;
  49 + const AMenuDivider = Menu.Divider;
  50 + const APopconfirm = Popconfirm;
  51 +
  52 + const props = defineProps({
  53 + popconfirm: Boolean,
  54 + /**
  55 + * the trigger mode which executes the drop-down action
  56 + * @default ['hover']
  57 + * @type string[]
  58 + */
  59 + trigger: {
  60 + type: [Array] as PropType<('contextmenu' | 'click' | 'hover')[]>,
  61 + default: () => {
  62 + return ['contextmenu'];
78 }, 63 },
79 }, 64 },
80 - emits: ['menuEvent'],  
81 - setup(props, { emit }) {  
82 - function handleClickMenu(item: DropMenu) {  
83 - const { event } = item;  
84 - const menu = props.dropMenuList.find((item) => `${item.event}` === `${event}`);  
85 - emit('menuEvent', menu);  
86 - item.onClick?.();  
87 - } 65 + dropMenuList: {
  66 + type: Array as PropType<(DropMenu & Recordable)[]>,
  67 + default: () => [],
  68 + },
  69 + selectedKeys: {
  70 + type: Array as PropType<string[]>,
  71 + default: () => [],
  72 + },
  73 + });
88 74
89 - const getPopConfirmAttrs = computed(() => {  
90 - return (attrs) => {  
91 - const originAttrs = omit(attrs, ['confirm', 'cancel', 'icon']);  
92 - if (!attrs.onConfirm && attrs.confirm && isFunction(attrs.confirm))  
93 - originAttrs['onConfirm'] = attrs.confirm;  
94 - if (!attrs.onCancel && attrs.cancel && isFunction(attrs.cancel))  
95 - originAttrs['onCancel'] = attrs.cancel;  
96 - return originAttrs;  
97 - };  
98 - }); 75 + const emit = defineEmits(['menuEvent']);
99 76
100 - return {  
101 - handleClickMenu,  
102 - getPopConfirmAttrs,  
103 - getAttr: (key: string | number) => ({ key }),  
104 - };  
105 - }, 77 + function handleClickMenu(item: DropMenu) {
  78 + const { event } = item;
  79 + const menu = props.dropMenuList.find((item) => `${item.event}` === `${event}`);
  80 + emit('menuEvent', menu);
  81 + item.onClick?.();
  82 + }
  83 +
  84 + const getPopConfirmAttrs = computed(() => {
  85 + return (attrs) => {
  86 + const originAttrs = omit(attrs, ['confirm', 'cancel', 'icon']);
  87 + if (!attrs.onConfirm && attrs.confirm && isFunction(attrs.confirm))
  88 + originAttrs['onConfirm'] = attrs.confirm;
  89 + if (!attrs.onCancel && attrs.cancel && isFunction(attrs.cancel))
  90 + originAttrs['onCancel'] = attrs.cancel;
  91 + return originAttrs;
  92 + };
106 }); 93 });
107 </script> 94 </script>
src/components/Icon/src/IconPicker.vue
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 v-model:value="currentSelect" 7 v-model:value="currentSelect"
8 > 8 >
9 <template #addonAfter> 9 <template #addonAfter>
10 - <Popover 10 + <a-popover
11 placement="bottomLeft" 11 placement="bottomLeft"
12 trigger="click" 12 trigger="click"
13 v-model="visible" 13 v-model="visible"
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 <div class="flex justify-between"> 17 <div class="flex justify-between">
18 <a-input 18 <a-input
19 :placeholder="t('component.icon.search')" 19 :placeholder="t('component.icon.search')"
20 - @change="handleSearchChange" 20 + @change="debounceHandleSearchChange"
21 allowClear 21 allowClear
22 /> 22 />
23 </div> 23 </div>
@@ -53,7 +53,7 @@ @@ -53,7 +53,7 @@
53 </ul> 53 </ul>
54 </ScrollContainer> 54 </ScrollContainer>
55 <div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize"> 55 <div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize">
56 - <Pagination 56 + <a-pagination
57 showLessItems 57 showLessItems
58 size="small" 58 size="small"
59 :pageSize="pageSize" 59 :pageSize="pageSize"
@@ -63,7 +63,7 @@ @@ -63,7 +63,7 @@
63 </div> 63 </div>
64 </div> 64 </div>
65 <template v-else 65 <template v-else
66 - ><div class="p-5"><Empty /></div> 66 + ><div class="p-5"><a-empty /></div>
67 </template> 67 </template>
68 </template> 68 </template>
69 69
@@ -71,16 +71,14 @@ @@ -71,16 +71,14 @@
71 <SvgIcon :name="currentSelect" /> 71 <SvgIcon :name="currentSelect" />
72 </span> 72 </span>
73 <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else /> 73 <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else />
74 - </Popover> 74 + </a-popover>
75 </template> 75 </template>
76 </a-input> 76 </a-input>
77 </template> 77 </template>
78 -<script lang="ts">  
79 - import { defineComponent, ref, watchEffect, watch, unref } from 'vue';  
80 - 78 +<script lang="ts" setup>
  79 + import { ref, watchEffect, watch, unref } from 'vue';
81 import { useDesign } from '/@/hooks/web/useDesign'; 80 import { useDesign } from '/@/hooks/web/useDesign';
82 import { ScrollContainer } from '/@/components/Container'; 81 import { ScrollContainer } from '/@/components/Container';
83 -  
84 import { Input, Popover, Pagination, Empty } from 'ant-design-vue'; 82 import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
85 import Icon from './Icon.vue'; 83 import Icon from './Icon.vue';
86 import SvgIcon from './SvgIcon.vue'; 84 import SvgIcon from './SvgIcon.vue';
@@ -94,6 +92,12 @@ @@ -94,6 +92,12 @@
94 import { useMessage } from '/@/hooks/web/useMessage'; 92 import { useMessage } from '/@/hooks/web/useMessage';
95 import svgIcons from 'virtual:svg-icons-names'; 93 import svgIcons from 'virtual:svg-icons-names';
96 94
  95 + // 没有使用别名引入,是因为WebStorm当前版本还不能正确识别,会报unused警告
  96 + const AInput = Input;
  97 + const APopover = Popover;
  98 + const APagination = Pagination;
  99 + const AEmpty = Empty;
  100 +
97 function getIcons() { 101 function getIcons() {
98 const data = iconsData as any; 102 const data = iconsData as any;
99 const prefix: string = data?.prefix ?? ''; 103 const prefix: string = data?.prefix ?? '';
@@ -110,88 +114,70 @@ @@ -110,88 +114,70 @@
110 return svgIcons.map((icon) => icon.replace('icon-', '')); 114 return svgIcons.map((icon) => icon.replace('icon-', ''));
111 } 115 }
112 116
113 - export default defineComponent({  
114 - name: 'IconPicker',  
115 - components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty, SvgIcon },  
116 - inheritAttrs: false,  
117 - props: {  
118 - value: propTypes.string,  
119 - width: propTypes.string.def('100%'),  
120 - pageSize: propTypes.number.def(140),  
121 - copy: propTypes.bool.def(false),  
122 - mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'), 117 + const props = defineProps({
  118 + value: propTypes.string,
  119 + width: propTypes.string.def('100%'),
  120 + pageSize: propTypes.number.def(140),
  121 + copy: propTypes.bool.def(false),
  122 + mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
  123 + });
  124 +
  125 + const emit = defineEmits(['change', 'update:value']);
  126 +
  127 + const isSvgMode = props.mode === 'svg';
  128 + const icons = isSvgMode ? getSvgIcons() : getIcons();
  129 +
  130 + const currentSelect = ref('');
  131 + const visible = ref(false);
  132 + const currentList = ref(icons);
  133 +
  134 + const { t } = useI18n();
  135 + const { prefixCls } = useDesign('icon-picker');
  136 +
  137 + const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);
  138 + const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);
  139 + const { createMessage } = useMessage();
  140 +
  141 + const { getPaginationList, getTotal, setCurrentPage } = usePagination(
  142 + currentList,
  143 + props.pageSize,
  144 + );
  145 +
  146 + watchEffect(() => {
  147 + currentSelect.value = props.value;
  148 + });
  149 +
  150 + watch(
  151 + () => currentSelect.value,
  152 + (v) => {
  153 + emit('update:value', v);
  154 + return emit('change', v);
123 }, 155 },
124 - emits: ['change', 'update:value'],  
125 - setup(props, { emit }) {  
126 - const isSvgMode = props.mode === 'svg';  
127 - const icons = isSvgMode ? getSvgIcons() : getIcons();  
128 -  
129 - const currentSelect = ref('');  
130 - const visible = ref(false);  
131 - const currentList = ref(icons);  
132 -  
133 - const { t } = useI18n();  
134 - const { prefixCls } = useDesign('icon-picker');  
135 -  
136 - const debounceHandleSearchChange = useDebounceFn(handleSearchChange, 100);  
137 - const { clipboardRef, isSuccessRef } = useCopyToClipboard(props.value);  
138 - const { createMessage } = useMessage();  
139 -  
140 - const { getPaginationList, getTotal, setCurrentPage } = usePagination(  
141 - currentList,  
142 - props.pageSize,  
143 - );  
144 -  
145 - watchEffect(() => {  
146 - currentSelect.value = props.value;  
147 - });  
148 -  
149 - watch(  
150 - () => currentSelect.value,  
151 - (v) => {  
152 - emit('update:value', v);  
153 - return emit('change', v);  
154 - },  
155 - );  
156 -  
157 - function handlePageChange(page: number) {  
158 - setCurrentPage(page);  
159 - } 156 + );
160 157
161 - function handleClick(icon: string) {  
162 - currentSelect.value = icon;  
163 - if (props.copy) {  
164 - clipboardRef.value = icon;  
165 - if (unref(isSuccessRef)) {  
166 - createMessage.success(t('component.icon.copy'));  
167 - }  
168 - }  
169 - } 158 + function handlePageChange(page: number) {
  159 + setCurrentPage(page);
  160 + }
170 161
171 - function handleSearchChange(e: ChangeEvent) {  
172 - const value = e.target.value;  
173 - if (!value) {  
174 - setCurrentPage(1);  
175 - currentList.value = icons;  
176 - return;  
177 - }  
178 - currentList.value = icons.filter((item) => item.includes(value)); 162 + function handleClick(icon: string) {
  163 + currentSelect.value = icon;
  164 + if (props.copy) {
  165 + clipboardRef.value = icon;
  166 + if (unref(isSuccessRef)) {
  167 + createMessage.success(t('component.icon.copy'));
179 } 168 }
  169 + }
  170 + }
180 171
181 - return {  
182 - t,  
183 - prefixCls,  
184 - visible,  
185 - isSvgMode,  
186 - getTotal,  
187 - getPaginationList,  
188 - handlePageChange,  
189 - handleClick,  
190 - currentSelect,  
191 - handleSearchChange: debounceHandleSearchChange,  
192 - };  
193 - },  
194 - }); 172 + function handleSearchChange(e: ChangeEvent) {
  173 + const value = e.target.value;
  174 + if (!value) {
  175 + setCurrentPage(1);
  176 + currentList.value = icons;
  177 + return;
  178 + }
  179 + currentList.value = icons.filter((item) => item.includes(value));
  180 + }
195 </script> 181 </script>
196 <style lang="less"> 182 <style lang="less">
197 @prefix-cls: ~'@{namespace}-icon-picker'; 183 @prefix-cls: ~'@{namespace}-icon-picker';