Repository: Tencent/tdesign-mobile-vue
Pull request #851 (2023-06-09 09:11:03)

fix(DropdownMenu): resolve a few issue
<!--
首先，感谢你的贡献！😄
请阅读并遵循 [TDesign 贡献指南](https://github.com/Tencent/tdesign/blob/main/docs/contributing.md)，填写以下 pull request 的信息。
PR 在维护者审核通过后会合并，谢谢！
-->

### 🤔 这个 PR 的性质是？

- [x] 日常 bug 修复
- [ ] 新特性提交
- [ ] 文档改进
- [ ] 演示代码改进
- [ ] 组件样式/交互改进
- [ ] CI/CD 改进
- [ ] 重构
- [ ] 代码风格优化
- [ ] 测试用例
- [ ] 分支合并
- [ ] 其他

### 🔗 相关 Issue

<!--
1. 描述相关需求的来源，如相关的 issue 讨论链接。
-->

### 💡 需求背景和解决方案

<!--
1. 要解决的具体问题。
2. 列出最终的 API 实现和用法。
3. 涉及UI/交互变动需要有截图或 GIF。
-->

### 📝 更新日志

<!--
从用户角度描述具体变化，以及可能的 breaking change 和其他风险。
-->

- fix(DropdownMenu): 修复 `closeOnClickOverlay` 属性无效的问题
- fix(DropdownMenu): 修复 `options` 初始值不能为空
- fix(DropdownMenu): 修复 `expose` 产生的告警问题

- [ ] 本条 PR 不需要纳入 Changelog

### ☑️ 请求合并前的自查清单

⚠️ 请自检并全部**勾选全部选项**。⚠️

- [x] 文档已补充或无须补充
- [x] 代码演示已提供或无须提供
- [x] TypeScript 定义已补充或无须补充
- [x] Changelog 已提供或无须提供


github-actions[bot]: <a href="https://preview-pr851-tdesign-mobile-vue.surge.sh"><img height="96" alt="完成" src="https://user-images.githubusercontent.com/15634204/150816437-9f5bb788-cd67-4cbc-9897-b82d74e9aa65.png" /></a>
<!-- [工作流地址](https://github.com/Tencent/tdesign-mobile-vue/actions/runs/5220298782) -->
<!-- AUTO_PREVIEW_HOOK -->

Patch:
diff --git a/src/dropdown-menu/dropdown-item.vue b/src/dropdown-menu/dropdown-item.vue
index 8b892f4f..3c149eed 100644
--- a/src/dropdown-menu/dropdown-item.vue
+++ b/src/dropdown-menu/dropdown-item.vue
@@ -1,7 +1,7 @@
 <template>
   <div v-if="wrapperVisible" :id="popupId" :class="classes" :style="{ ...expandStyle }">
     <t-popup
-      v-model="isShowItems"
+      :visible="isShowItems"
       :duration="duration"
       :show-overlay="showOverlay"
       :style="popupStyle"
@@ -9,7 +9,6 @@
       :class="`${name}__popup-host`"
       :attach="`#${popupId}`"
       @visible-change="onVisibleChange"
-      @close="closePopup"
     >
       <div :class="styleContent">
         <div :class="`${name}__body`">
@@ -196,9 +195,6 @@ export default defineComponent({
         checkSelect.value = (val ?? []) as DropdownValue[];
       }
     };
-    const closePopup = () => {
-      collapseMenu();
-    };
     // 初始值更新一次选中项
     updateSelectValue(passInValue.value || null);
     // 跟踪 modelValue 更新选项
@@ -276,7 +272,6 @@ export default defineComponent({
       radioSelect,
       checkSelect,
       popupId,
-      closePopup,
       isCheckedRadio,
       styleDropRadio,
       expandMenu,
diff --git a/src/dropdown-menu/dropdown-menu.vue b/src/dropdown-menu/dropdown-menu.vue
index 6ffe504f..515a80fd 100644
--- a/src/dropdown-menu/dropdown-menu.vue
+++ b/src/dropdown-menu/dropdown-menu.vue
@@ -22,7 +22,7 @@ import {
   TriggerSource,
 } from './context';
 import TransAniControl from './trans-ani-control';
-import { useEmitEvent } from '../shared';
+import { useEmitEvent, useExpose } from '../shared';
 import { findRelativeRect, findRelativeContainer } from './dom-utils';
 import DropdownMenuProps from './props';
 
@@ -34,7 +34,7 @@ export default defineComponent({
   components: { CaretDownSmallIcon },
   props: DropdownMenuProps,
   emits: ['menuOpened', 'menuClosed'],
-  setup(props, { slots, expose, emit }) {
+  setup(props, { slots, emit }) {
     const emitEvent = useEmitEvent(props, emit);
     // 菜单状态
     const state = reactive<DropdownMenuState>({
@@ -67,7 +67,7 @@ export default defineComponent({
         const { keys, label, value, disabled, options } = item.props;
         const target = options?.find((item: any) => item[keys?.value ?? 'value'] === value);
         if (!label) {
-          state.itemsLabel.push(target[keys?.label ?? 'label'] || '');
+          state.itemsLabel.push((target && target[keys?.label ?? 'label']) || '');
         }
         const computedLabel = target?.[keys?.label ?? 'label'] || '';
         return {
@@ -144,7 +144,7 @@ export default defineComponent({
     const control: DropdownMenuControl = { expandMenu, collapseMenu, emitEvents };
     // 提供子组件访问
     provide('dropdownMenuControl', control);
-    expose({
+    useExpose({
       toggle(idx?: number) {
         if (idx != null) {
           const item = menuTitles.value[idx];
@@ -155,7 +155,7 @@ export default defineComponent({
       },
     });
 
-    expose({
+    useExpose({
       expandMenu,
       collapseMenu,
     });


Test patch:
diff --git a/src/grid/__test__/index.test.jsx b/src/grid/__test__/index.test.jsx
index a6da180b..f654b10c 100644
--- a/src/grid/__test__/index.test.jsx
+++ b/src/grid/__test__/index.test.jsx
@@ -31,30 +31,40 @@ const items2 = [
 ];
 describe('grid', () => {
   describe('props', () => {
-    it(':align ', async () => {
-      const align = 'left';
-      const wrapper = mount({
-        setup() {
-          return () => (
-            <Grid align={align}>
-              {{
-                default: items.map((item, index) => {
-                  return <GridItem text={item.text + index} image={item.image} />;
-                }),
-              }}
+    it(':align', async () => {
+      const alignList = ['left', 'center', ''];
+      alignList.map((a) => {
+        const wrapper = mount(() => {
+          return (
+            <Grid align={a}>
+              <GridItem />
             </Grid>
           );
-        },
+        });
+        const $gridItem = wrapper.find('.t-grid-item');
+        if (a === 'left') {
+          expect($gridItem.element.style.textAlign).toBe('left');
+        } else {
+          expect($gridItem.element.style.textAlign).toBe('center');
+        }
       });
-      expect(wrapper.findComponent(Grid).exists()).toBeTruthy();
-      expect(wrapper.findAllComponents(GridItem).length).toEqual(items.length);
-      const $gridItems = wrapper.findAll(`.${name}-item`);
-      // align = 'left (自定义)
-      // border = false, column = 4, gutter = 0 (默认)
-      $gridItems.map((item) => {
-        expect(item.attributes('class').includes(`${name}-item--bordered`)).toBeFalsy(); // border
-        expect(item.element.style.textAlign).toBe('left'); // align
-        expect(item.element.style.flexBasis).toBe(`${100 / 4}%`); // column
+    });
+
+    it(':theme', async () => {
+      const themeList = ['default', 'card', ''];
+      themeList.map((t) => {
+        const wrapper = mount(() => {
+          return (
+            <Grid theme={t}>
+              <GridItem />
+            </Grid>
+          );
+        });
+        if (t === 'card') {
+          expect(wrapper.find(`.t-grid--card`).exists()).toBe(true);
+        } else {
+          expect(wrapper.find(`.t-grid--card`).exists()).toBe(false);
+        }
       });
     });
 
@@ -105,6 +115,17 @@ describe('grid', () => {
         expect(item.element.style.flexBasis).toBe(`${100 / column}%`); // column
       });
     });
+
+    it(':column = 0', async () => {
+      const wrapper = mount(() => {
+        return (
+          <Grid column={0}>
+            <GridItem></GridItem>
+          </Grid>
+        );
+      });
+      expect(wrapper.find('.t-grid--auto-size').exists()).toBeTruthy();
+    });
   });
 });
 
@@ -149,4 +170,20 @@ describe('grid-item', () => {
     expect(badge.exists()).toBeTruthy();
     expect(badge.text()).toBe('1');
   });
+
+  it(':layout', async () => {
+    const layoutList = ['vertical', 'horizontal', ''];
+    layoutList.map((l) => {
+      const wrapper = mount(() => {
+        return (
+          <Grid>
+            <GridItem layout={l} />
+          </Grid>
+        );
+      });
+      if (l) { 
+        expect(wrapper.find('.t-grid-item').classes()).toContain(`t-grid-item--${l}`); 
+      }
+    });
+  });
 });