Tencent / tdesign-miniprogram

A Wechat MiniProgram UI components lib for TDesign.
https://tdesign.tencent.com/miniprogram
MIT License
1.24k stars 280 forks source link

[Dialog] 偶发现出现画面跳转再返回后,弹窗关闭但遮罩层还在的现象 #2827

Open Zlianxin opened 6 months ago

Zlianxin commented 6 months ago

tdesign-miniprogram 版本

1.2.0

重现链接

No response

重现步骤

代码如下所示:

const showDialog = {
  content: res.message,
  confirmBtn: '去购买押金',
  cancelBtn: '取消'
};
Dialog.confirm(showDialog).then(()=> {
  wx.navigateTo({
    url: '../../usercenter/deposit/index',
  });
}).catch(() => console.log('点击了取消'))
.finally(() => Dialog.close());

期望结果

点击按钮跳转到下一页返回之后,页面能够正常点击,无异常

实际结果

偶然会出现返回之后,遮罩层还在画面上,画面无法点击的情况。 现象和真机调试的结果,通过图片和视频上传了。

之后尝试了不用命令行控制,用visible的那个方式,也是不行,也会出现偶发的不可点击的现象。 再之后也尝试了,把画面跳转写到wx.navigateTo的complete回调里面,也不行。。。

https://github.com/Tencent/tdesign-miniprogram/assets/38103260/01f4861f-0e9b-414a-ba0c-6eff51054414

微信图片_20240531153033 微信图片_20240531153036

基础库版本

No response

补充说明

No response

github-actions[bot] commented 6 months ago

👋 @Zlianxin,感谢给 TDesign 提出了 issue。 请根据 issue 模版确保背景信息的完善,我们将调查并尽快回复你。

anlyyao commented 6 months ago

@Zlianxin 我来跟进看看~

Zlianxin commented 6 months ago

@Zlianxin 我来跟进看看~

感觉像是popup的问题,项目中有人用popup画了一个弹窗,上面有两个按钮。 其中一个按钮点击之后是跳转画面,返回之后,依旧出现类似的情况,遮罩层还在~

Zlianxin commented 6 months ago

@Zlianxin 我来跟进看看~

我把项目中的代码抽离出了一部分,单独写了份代码,放在gitee上面了。 仓库地址:https://gitee.com/jinyun0927/question_20240604 里面除了代码之外,还有演示的录屏,反复点击,一直到50s后现象复现了,即跳转画面返回后,画面点击无响应。 测试设备是华为Mate40。

jarmywang commented 6 months ago

@Zlianxin 麻烦你那边试试用这段代码覆盖你示例(仓库地址:https://gitee.com/jinyun0927/question_20240604 )里的/question_20240604-master/miniprogram-5/miniprogram_npm/tdesign-miniprogram/mixins/transition.js文件:

import config from "../common/config";
const { prefix } = config;
export default function transition() {
  return Behavior({
    properties: {
      visible: {
        type: Boolean,
        value: null,
        observer: "watchVisible",
      },
      appear: Boolean,
      name: {
        type: String,
        value: "fade",
      },
      durations: {
        type: Number,
        optionalTypes: [Array],
      },
    },
    data: {
      transitionClass: "",
      transitionDurations: 300,
      className: "",
      realVisible: false,
    },
    created() {
      this.status = "";
      this.transitionT = 0;
    },
    attached() {
      this.durations = this.getDurations();
      if (this.data.visible) {
        this.enter();
      }
      this.inited = true;
    },
    detached() {
      clearTimeout(this.transitionT);
    },
    methods: {
      watchVisible(curr, prev) {
        if (this.inited && curr !== prev) {
          curr ? this.enter() : this.leave();
        }
      },
      getDurations() {
        const { durations } = this.data;
        if (Array.isArray(durations)) {
          return durations.map((item) => Number(item));
        }
        return [Number(durations), Number(durations)];
      },
      enter() {
        const { name } = this.data;
        const [duration] = this.durations;
        this.status = "entering";
        this.setData(
          {
            realVisible: true,
            transitionClass: `${prefix}-${name}-enter ${prefix}-${name}-enter-active`,
          },
          () => {
            this.setData(
              {
                transitionClass: `${prefix}-${name}-enter-active ${prefix}-${name}-enter-to`,
              },
              () => {
                if (typeof duration === "number" && duration > 0) {
                  this.transitionT = setTimeout(
                    this.entered.bind(this),
                    duration
                  );
                }
              }
            );
          }
        );
      },
      entered() {
        this.customDuration = false;
        clearTimeout(this.transitionT);
        this.status = "entered";
        this.setData({
          transitionClass: "",
        });
      },
      leave() {
        const { name } = this.data;
        const [, duration] = this.durations;
        this.status = "leaving";
        this.setData(
          {
            transitionClass: `${prefix}-${name}-leave  ${prefix}-${name}-leave-active`,
          },
          () => {
            this.setData(
              {
                transitionClass: `${prefix}-${name}-leave-active ${prefix}-${name}-leave-to`,
              },
              () => {
                if (typeof duration === "number" && duration > 0) {
                  this.customDuration = true;
                  this.transitionT = setTimeout(
                    this.leaved.bind(this),
                    duration
                  );
                }
              }
            );
          }
        );
        clearTimeout(this.transitionT);
      },
      leaved() {
        this.customDuration = false;
        this.triggerEvent("leaved");
        clearTimeout(this.transitionT);
        this.status = "leaved";
        this.setData({
          transitionClass: "",
        });
      },
      onTransitionEnd() {
        if (this.customDuration) {
          return;
        }
        clearTimeout(this.transitionT);
        if (this.status === "entering" && this.data.visible) {
          this.entered();
        } else if (this.status === "leaving" && !this.data.visible) {
          this.leaved();
          this.setData({
            realVisible: false,
          });
        }
      },
    },
  });
}
jarmywang commented 6 months ago

@Zlianxin 怀疑页面跳转引发了小程序内部的时序问题,建议跳转加一点延迟,等弹层动画消失再跳转体验上更好,同时有可能规避掉此问题

    setTimeout(() => {
      wx.navigateTo({
        url: "../test/index",
      });
    }, 300);
Zlianxin commented 6 months ago

@Zlianxin 麻烦你那边试试用这段代码覆盖你示例(仓库地址:https://gitee.com/jinyun0927/question_20240604 )里的/question_20240604-master/miniprogram-5/miniprogram_npm/tdesign-miniprogram/mixins/transition.js文件:

import config from "../common/config";
const { prefix } = config;
export default function transition() {
  return Behavior({
    properties: {
      visible: {
        type: Boolean,
        value: null,
        observer: "watchVisible",
      },
      appear: Boolean,
      name: {
        type: String,
        value: "fade",
      },
      durations: {
        type: Number,
        optionalTypes: [Array],
      },
    },
    data: {
      transitionClass: "",
      transitionDurations: 300,
      className: "",
      realVisible: false,
    },
    created() {
      this.status = "";
      this.transitionT = 0;
    },
    attached() {
      this.durations = this.getDurations();
      if (this.data.visible) {
        this.enter();
      }
      this.inited = true;
    },
    detached() {
      clearTimeout(this.transitionT);
    },
    methods: {
      watchVisible(curr, prev) {
        if (this.inited && curr !== prev) {
          curr ? this.enter() : this.leave();
        }
      },
      getDurations() {
        const { durations } = this.data;
        if (Array.isArray(durations)) {
          return durations.map((item) => Number(item));
        }
        return [Number(durations), Number(durations)];
      },
      enter() {
        const { name } = this.data;
        const [duration] = this.durations;
        this.status = "entering";
        this.setData(
          {
            realVisible: true,
            transitionClass: `${prefix}-${name}-enter ${prefix}-${name}-enter-active`,
          },
          () => {
            this.setData(
              {
                transitionClass: `${prefix}-${name}-enter-active ${prefix}-${name}-enter-to`,
              },
              () => {
                if (typeof duration === "number" && duration > 0) {
                  this.transitionT = setTimeout(
                    this.entered.bind(this),
                    duration
                  );
                }
              }
            );
          }
        );
      },
      entered() {
        this.customDuration = false;
        clearTimeout(this.transitionT);
        this.status = "entered";
        this.setData({
          transitionClass: "",
        });
      },
      leave() {
        const { name } = this.data;
        const [, duration] = this.durations;
        this.status = "leaving";
        this.setData(
          {
            transitionClass: `${prefix}-${name}-leave  ${prefix}-${name}-leave-active`,
          },
          () => {
            this.setData(
              {
                transitionClass: `${prefix}-${name}-leave-active ${prefix}-${name}-leave-to`,
              },
              () => {
                if (typeof duration === "number" && duration > 0) {
                  this.customDuration = true;
                  this.transitionT = setTimeout(
                    this.leaved.bind(this),
                    duration
                  );
                }
              }
            );
          }
        );
        clearTimeout(this.transitionT);
      },
      leaved() {
        this.customDuration = false;
        this.triggerEvent("leaved");
        clearTimeout(this.transitionT);
        this.status = "leaved";
        this.setData({
          transitionClass: "",
        });
      },
      onTransitionEnd() {
        if (this.customDuration) {
          return;
        }
        clearTimeout(this.transitionT);
        if (this.status === "entering" && this.data.visible) {
          this.entered();
        } else if (this.status === "leaving" && !this.data.visible) {
          this.leaved();
          this.setData({
            realVisible: false,
          });
        }
      },
    },
  });
}

代码替换之后,点击了20次左右吧,问题还是复现了

jarmywang commented 6 months ago

@Zlianxin 怀疑页面跳转引发了小程序内部的时序问题,建议跳转加一点延迟,等弹层动画消失再跳转体验上更好,同时有可能规避掉此问题

    setTimeout(() => {
      wx.navigateTo({
        url: "../test/index",
      });
    }, 300);

@Zlianxin 请问这里有尝试吗?我这边一直没有复现

Zlianxin commented 6 months ago

@Zlianxin 怀疑页面跳转引发了小程序内部的时序问题,建议跳转加一点延迟,等弹层动画消失再跳转体验上更好,同时有可能规避掉此问题

    setTimeout(() => {
      wx.navigateTo({
        url: "../test/index",
      });
    }, 300);

@Zlianxin 请问这里有尝试吗?我这边一直没有复现

加延迟一直是好用的,不改transition.js也可以

xieerduos commented 5 months ago

这么写能规避99.99% popup的问题,popup官方的组件有bug,bug复现:打开弹窗,点击跳转到新页面,同时跳转前设置visible为false,再返回上一个页面发现,弹窗虽然看见是隐藏的,但是popup还在所以点击页面会无反应,所以加上wx:if指令可以解决跳转页面在返回popup还存在的问题

<t-popup wx:if="{{visible}}" visible="{{visible}}" bind:visible-change="onVisibleChange" placement="bottom" style="--td-popup-border-radius:43rpx;">
  // .... 
</t-popup>

  /**
   * 组件的初始数据
   */
  data: {
    visible: false,
    },
// ...
  onVisibleChange(event) {
      const visible = event.detail.visible;
      this.setData({visible});
      this.triggerEvent('visible-change', visible);
    },
myifeng commented 4 months ago

同华为鸿蒙系统复现,其他正常