Browse Source

fix: hmr error fixed

修复部分组件可能会造成热更新异常的问题
无木 3 years ago
parent
commit
5af452754b
3 changed files with 128 additions and 153 deletions
  1. 3 1
      CHANGELOG.zh_CN.md
  2. 53 66
      src/components/Dropdown/src/Dropdown.vue
  3. 72 86
      src/components/Icon/src/IconPicker.vue

+ 3 - 1
CHANGELOG.zh_CN.md

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

+ 53 - 66
src/components/Dropdown/src/Dropdown.vue

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

+ 72 - 86
src/components/Icon/src/IconPicker.vue

@@ -7,7 +7,7 @@
     v-model:value="currentSelect"
   >
     <template #addonAfter>
-      <Popover
+      <a-popover
         placement="bottomLeft"
         trigger="click"
         v-model="visible"
@@ -17,7 +17,7 @@
           <div class="flex justify-between">
             <a-input
               :placeholder="t('component.icon.search')"
-              @change="handleSearchChange"
+              @change="debounceHandleSearchChange"
               allowClear
             />
           </div>
@@ -53,7 +53,7 @@
               </ul>
             </ScrollContainer>
             <div class="flex py-2 items-center justify-center" v-if="getTotal >= pageSize">
-              <Pagination
+              <a-pagination
                 showLessItems
                 size="small"
                 :pageSize="pageSize"
@@ -63,7 +63,7 @@
             </div>
           </div>
           <template v-else
-            ><div class="p-5"><Empty /></div>
+            ><div class="p-5"><a-empty /></div>
           </template>
         </template>
 
@@ -71,16 +71,14 @@
           <SvgIcon :name="currentSelect" />
         </span>
         <Icon :icon="currentSelect || 'ion:apps-outline'" class="cursor-pointer px-2 py-1" v-else />
-      </Popover>
+      </a-popover>
     </template>
   </a-input>
 </template>
-<script lang="ts">
-  import { defineComponent, ref, watchEffect, watch, unref } from 'vue';
-
+<script lang="ts" setup>
+  import { ref, watchEffect, watch, unref } from 'vue';
   import { useDesign } from '/@/hooks/web/useDesign';
   import { ScrollContainer } from '/@/components/Container';
-
   import { Input, Popover, Pagination, Empty } from 'ant-design-vue';
   import Icon from './Icon.vue';
   import SvgIcon from './SvgIcon.vue';
@@ -94,6 +92,12 @@
   import { useMessage } from '/@/hooks/web/useMessage';
   import svgIcons from 'virtual:svg-icons-names';
 
+  // 没有使用别名引入,是因为WebStorm当前版本还不能正确识别,会报unused警告
+  const AInput = Input;
+  const APopover = Popover;
+  const APagination = Pagination;
+  const AEmpty = Empty;
+
   function getIcons() {
     const data = iconsData as any;
     const prefix: string = data?.prefix ?? '';
@@ -110,88 +114,70 @@
     return svgIcons.map((icon) => icon.replace('icon-', ''));
   }
 
-  export default defineComponent({
-    name: 'IconPicker',
-    components: { [Input.name]: Input, Icon, Popover, ScrollContainer, Pagination, Empty, SvgIcon },
-    inheritAttrs: false,
-    props: {
-      value: propTypes.string,
-      width: propTypes.string.def('100%'),
-      pageSize: propTypes.number.def(140),
-      copy: propTypes.bool.def(false),
-      mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
+  const props = defineProps({
+    value: propTypes.string,
+    width: propTypes.string.def('100%'),
+    pageSize: propTypes.number.def(140),
+    copy: propTypes.bool.def(false),
+    mode: propTypes.oneOf<('svg' | 'iconify')[]>(['svg', 'iconify']).def('iconify'),
+  });
+
+  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);
     },
-    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 handlePageChange(page: number) {
+    setCurrentPage(page);
+  }
 
-      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));
+  function handleClick(icon: string) {
+    currentSelect.value = icon;
+    if (props.copy) {
+      clipboardRef.value = icon;
+      if (unref(isSuccessRef)) {
+        createMessage.success(t('component.icon.copy'));
       }
+    }
+  }
 
-      return {
-        t,
-        prefixCls,
-        visible,
-        isSvgMode,
-        getTotal,
-        getPaginationList,
-        handlePageChange,
-        handleClick,
-        currentSelect,
-        handleSearchChange: debounceHandleSearchChange,
-      };
-    },
-  });
+  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>
 <style lang="less">
   @prefix-cls: ~'@{namespace}-icon-picker';