关于ref哪怕在$nextTick()中有时候获取不到节点元素的问题。(较为诡异的bug)

我的需求是用element-ui的messagebox,来实现验证码接受的功能。并将cancel按钮换成刷新功能,在beforeClose中实现验证码刷新。元素都是在$msgbox中生成的,下面是最开始出错的核心代码。

        let result = await this.$API.reqCaptchaImg();
        this.captchaImg = "data:image/png;base64," + result.img;
        this.uuid = result.uuid;

        const h = this.$createElement;
        const inputElem = h(
          "input",
          {
            attrs: {
              value: this.inputCaptcha,
              id: "input1",
            },
            on: {
              input: function (event) {
                this.inputCaptcha = event.target.value;
              }.bind(this),
            },
          },
          ""
        );
        const imgElem = h("img", {
          ref: "captchaImg",
          
          attrs: {
            src: this.captchaImg,
          },
        });

        // 将 input 和 img 元素放到 Vue 组件之外的 div 中
        const divElem = h("div", [inputElem, imgElem]);
        await this.$msgbox({
          title: "Please enter the verification code",
          message: divElem,
          type: "warning",
          center: true,
          showCancelButton: true,
          confirmButtonText: "confirm",
          cancelButtonText: "refresh",
          distinguishCancelAndClose: true,
          beforeClose: async (action, instance, done) => {
            // console.log(action);
            if (action === "confirm") {
              flag = true;
              done();
            } else if (action === "cancel") {
              let result = await this.$API.reqCaptchaImg();

              this.captchaImg = "data:image/png;base64," + result.img;
              this.uuid = result.uuid;

              this.$nextTick(() => {
                // 更新captchaImg元素的src属性
                this.$refs.captchaImg.src = this.captchaImg;      
              });
            } else {
              flag = false;
              done();
            }
          },
        })
          .then((action) => {})
          .catch((action) => {});

其中,通过解决方法,可知错误主要集中在这俩处。

        const imgElem = h("img", {
          ref: "captchaImg",
          
          attrs: {
            src: this.captchaImg,
          },
        });

              this.$nextTick(() => {
                // 更新captchaImg元素的src属性
                this.$refs.captchaImg.src = this.captchaImg;      
              });

这样写,之后,出现了非常奇怪的bug。我测试的过程中,大部分时候的刷新验证码功能是完好的。但有时候就会出现无法获取ref元素的情况。出现下面的报错。

Error in nextTick: "TypeError: Cannot set properties of undefined (setting 'src')"

  1. 第一个奇怪的地方:首次出现验证码界面时,每一次都是正常显示的。只有点击刷新时,才有可能会出现报错。这说明节点元素明明已经更新到页面上了,但后续确找不到ref绑定。且报错会一直存在。除非手动刷新浏览器,才能正常刷新验证码。

  1. 第二个奇怪的地方:开发的时候,我发现报错是偶尔才会出现的,但一直不清楚报错出现的情况。后来,我发现:如果你每次都手动刷新浏览器,功能是正常的。但如果你是修改了代码,哪怕只是删了一行注释。然后ctrl+s保存,vue帮你自动刷新页面。你再重新打开messagebox刷新验证码,便会出现ref找不到绑定的情况。

在全网论坛上寻找原因,并没有找到解决方法。后面在chatgpt上寻找原因,发现chatgpt也不是万能的,最开始几次提供的都是错误的思路。(包括但不限于清除浏览器缓存,divElem放到msgbox外面,为$refs.captchaImg提供初始图片等)

多试了几次后,gpt找到了正确的方法。如下:尝试将 $refs.captchaImg 替换为 document.getElementById('captcha-img')。修改后代码的核心如下:

        const imgElem = h("img", {
          //不要这个
          //ref: "captchaImg",
          
          attrs: {
            src: this.captchaImg,
            //要这个
            id:"captcha-img",
          },
          style: {
            "margin-top": "20px",
          },
        });

              this.$nextTick(() => {
                // 更新captchaImg元素的src属性
                // this.$refs.captchaImg.src = this.captchaImg;
                document.getElementById('captcha-img').src = this.captchaImg;
              });

关于为什么使用ref会出现这么诡异的bug,id却不会。gpt解释如下:

问题是解决了,但是这并没有打消我对前面两个问题的疑问。先写一篇文章放在这里,等待后续再来回顾。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值