Commit 5af452754b0567539e6ba6899ce91fa2914a4829

Authored by 无木
1 parent 9c5f11a5

fix: hmr error fixed

修复部分组件可能会造成热更新异常的问题
CHANGELOG.zh_CN.md
... ... @@ -16,7 +16,9 @@
16 16 - 修复点击关闭按钮、最大化按钮旁边的空白区域也会导致`Modal`关闭的问题
17 17 - **BasicTree** 修复节点插槽不起作用的问题
18 18 - **CodeEditor** 修复可能会造成的`Build`失败的问题
19   -- **其它** 修复多标签在某些情况下关闭页签不会跳转路由的问题
  19 +- **其它**
  20 + - 修复多标签在某些情况下关闭页签不会跳转路由的问题
  21 + - 修复部分组件可能会造成热更新异常的问题
20 22  
21 23 ## 2.7.2(2021-09-14)
22 24  
... ...
src/components/Dropdown/src/Dropdown.vue
1 1 <template>
2   - <Dropdown :trigger="trigger" v-bind="$attrs">
  2 + <a-dropdown :trigger="trigger" v-bind="$attrs">
3 3 <span>
4 4 <slot></slot>
5 5 </span>
6 6 <template #overlay>
7   - <Menu :selectedKeys="selectedKeys">
  7 + <a-menu :selectedKeys="selectedKeys">
8 8 <template v-for="item in dropMenuList" :key="`${item.event}`">
9   - <MenuItem
  9 + <a-menu-item
10 10 v-bind="getAttr(item.event)"
11 11 @click="handleClickMenu(item)"
12 12 :disabled="item.disabled"
13 13 >
14   - <Popconfirm
  14 + <a-popconfirm
15 15 v-if="popconfirm && item.popConfirm"
16 16 v-bind="getPopConfirmAttrs(item.popConfirm)"
17 17 >
... ... @@ -22,86 +22,73 @@
22 22 <Icon :icon="item.icon" v-if="item.icon" />
23 23 <span class="ml-1">{{ item.text }}</span>
24 24 </div>
25   - </Popconfirm>
  25 + </a-popconfirm>
26 26 <template v-else>
27 27 <Icon :icon="item.icon" v-if="item.icon" />
28 28 <span class="ml-1">{{ item.text }}</span>
29 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 32 </template>
33   - </Menu>
  33 + </a-menu>
34 34 </template>
35   - </Dropdown>
  35 + </a-dropdown>
36 36 </template>
37 37  
38   -<script lang="ts">
  38 +<script lang="ts" setup>
39 39 import { computed, PropType } from 'vue';
40 40 import type { DropMenu } from './typing';
41   -
42   - import { defineComponent } from 'vue';
43 41 import { Dropdown, Menu, Popconfirm } from 'ant-design-vue';
44 42 import { Icon } from '/@/components/Icon';
45 43 import { omit } from 'lodash-es';
46 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 94 </script>
... ...
src/components/Icon/src/IconPicker.vue
... ... @@ -7,7 +7,7 @@
7 7 v-model:value="currentSelect"
8 8 >
9 9 <template #addonAfter>
10   - <Popover
  10 + <a-popover
11 11 placement="bottomLeft"
12 12 trigger="click"
13 13 v-model="visible"
... ... @@ -17,7 +17,7 @@
17 17 <div class="flex justify-between">
18 18 <a-input
19 19 :placeholder="t('component.icon.search')"
20   - @change="handleSearchChange"
  20 + @change="debounceHandleSearchChange"
21 21 allowClear
22 22 />
23 23 </div>
... ... @@ -53,7 +53,7 @@
53 53 </ul>
54 54 </ScrollContainer>
55 55 <div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize">
56   - <Pagination
  56 + <a-pagination
57 57 showLessItems
58 58 size="small"
59 59 :pageSize="pageSize"
... ... @@ -63,7 +63,7 @@
63 63 </div>
64 64 </div>
65 65 <template v-else
66   - ><div class="p-5"><Empty /></div>
  66 + ><div class="p-5"><a-empty /></div>
67 67 </template>
68 68 </template>
69 69  
... ... @@ -71,16 +71,14 @@
71 71 <SvgIcon :name="currentSelect" />
72 72 </span>
73 73 <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else />
74   - </Popover>
  74 + </a-popover>
75 75 </template>
76 76 </a-input>
77 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 80 import { useDesign } from '/@/hooks/web/useDesign';
82 81 import { ScrollContainer } from '/@/components/Container';
83   -
84 82 import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
85 83 import Icon from './Icon.vue';
86 84 import SvgIcon from './SvgIcon.vue';
... ... @@ -94,6 +92,12 @@
94 92 import { useMessage } from '/@/hooks/web/useMessage';
95 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 101 function getIcons() {
98 102 const data = iconsData as any;
99 103 const prefix: string = data?.prefix ?? '';
... ... @@ -110,88 +114,70 @@
110 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 181 </script>
196 182 <style lang="less">
197 183 @prefix-cls: ~'@{namespace}-icon-picker';
... ...