记录在做项目中遇到的Input输入框失焦事件无效问题及解决思路

问题

场景演示

在这里插入图片描述
从动图可以看到,当第一次点击文本时,文本变为可编辑状态,但点击文本框以外的地方,文本框并没有关闭编辑状态。而需要重新点击文本框,再点击外面才有效果。

代码片段

<div class="flex items-center">
      <span>昵称:</span>
      <span
        v-if="isEditName"
        class="cursor-pointer font-bold"
        @click="handleEditName"
      >
        {{ name }}
      </span>
      <input
        class="ring-2"
        v-else
        v-model="name"
        type="text"
        @blur="submitEditName"
        @keyup.enter="submitEditName"
      />
    </div>
export default {
  data() {
    return {
      isEditName: true,
      name: "LynnHg",
    };
  },
  methods: {
    handleEditName() {
      this.isEditName = false;
    },
    async submitEditName() {
      this.isEditName = true;
      // 发请求保存修改后的数据
      // ...
    },
  },
};

问题简单描述

需求是做一个文本展示,点击文本切换为可编辑的输入框,点击输入框以外的地方保存修改后的内容。

遇到的问题是:点击输入框以外的地方并没有触发失焦事件。只有再次点击并聚焦输入框,再点击输入框以外的地方,失焦事件才能触发。

解决思路

问题出现的原因分析

我们通过if else来控制文本和输入框的切换,当点击文本时触发handleEditName函数,将isEditName = false,达到else条件,从而渲染inout框。

blur表示对象失去焦点时触发,而我们的input框是通过条件渲染生成的,并不是通过聚焦事件focus触发的。

因此,当我们点击输入框以外的地方并没有触发blur事件。

解决办法

我们要在input框渲染出来的时候,聚焦到input框上。
input 加上ref属性。

<input
  class="ring-2"
  ref="nameInput"
  v-else
  v-model="name"
  type="text"
  @blur="submitEditName"
  @keyup.enter="submitEditName"
 />

handleEditName函数中增加以下代码:

handleEditName() {
  this.isEditName = false;
  this.$refs.nameInput.focus();
},

保存代码,再次运行回到界面。

结果问题还是没有解决,而且会报以下错误。怎么回事呢?

Error in v-on handler: "TypeError: Cannot read property 'focus' of undefined"

这里就涉及到Vue的响应式原理了,大概就是我们通过this.isEditName = false来切换input显示,但是这一行代码不会立即让组件重新渲染,而我们又近接着在下一行代码中通过this.$refs去获取input的实例,其实是拿不到的。

详细原理请参考深入响应式原理-异步更新队列

应该怎么办呢?

两种解决思路

1.定时器 setTimeout()

handleEditName() {
  this.isEditName = false;
  setTimeout(() => {
    this.$refs.nameInput.focus();
  });
},

2.nextTick()

handleEditName() {
  this.isEditName = false;
  this.$nextTick(function () {
    this.$refs.nameInput.focus();
  });
},

效果演示

忽略光标显示问题,应该是录制gif时卡了。
在这里插入图片描述
问题完美解决,nice!!!

源码参考

Logo

Vue社区为您提供最前沿的新闻资讯和知识内容

更多推荐