当前位置: 首页 > article >正文

Uniapp踩坑input自动获取焦点ref动态获取实例不可用

前言

大家好我是没钱的君子下流坯,用自己的话解释自己的知识。很久很更新了,这几个月一直在加班,今天记录一个uniapp关于input中focus()方法自动获取焦点的坑。

案例

为了实现一个手机验证码的页面,验证码是五个输入框,输入第一个输入框后焦点自动获取到下一个输入框的焦点如图所示:在这里插入图片描述

实现思路

我的思路是给每个输入框动态绑定一个ref实例去调用实例上的focus()方法,我第一次的代码也是这样写的代码如下所示:

<template>
  <view class="container">
    <view class="otp-container">
      <input
        v-for="(item, index) in otpLength"
        :key="index"
        type="tel"
        maxlength="1"
        @input="onInput($event, index)"
        @focus="onFocus(index)"
        :ref="`input-${index}`"
        class="otp-input"
      />
    </view>
    <button @click="submitOTP">提交</button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      otpLength: 5,         // 验证码的长度
      otpValues: ['', '', '', '', ''],  // 存储每个输入框的值
      activeIndex: null     // 当前聚焦的输入框索引
    };
  },
  methods: {
    onInput(event, index) {
      const value = event.target.value;
      this.$set(this.otpValues, index, value);  // 更新对应输入框的值

      if (value && index < this.otpLength - 1) {
        this.$nextTick(() => {
          this.focusNextInput(index + 1);  // 自动跳转到下一个输入框
        });
      }
    },
    onFocus(index) {
      this.activeIndex = index;  // 记录当前聚焦的输入框索引
    },
    focusNextInput(index) {
      console.log(`Trying to focus input-${index}`);
      console.log('this.$refs:', this.$refs);
      const ref = this.$refs[`input-${index}`];
      if (ref && Array.isArray(ref) && ref.length > 0) {
        ref[0].focus();  // 确保引用存在再调用 focus 方法
      } else {
        console.error(`Reference for input-${index} not found or invalid`, ref);
      }
    },
    submitOTP() {
      const otp = this.otpValues.join('');  // 将所有输入框的值拼接成一个字符串
      console.log('提交的验证码:', otp);  // 打印验证码
      // 这里可以添加提交验证码的逻辑
    }
  }
};
</script>

尝试方法1加判断排除DOM渲染

但是一直报错说 "TypeError: this.$refs["input-".concat(...)][0].focus is not a function" 我心想这怎么可能不是个函数难道未定义,我就抓紧打印ref发现是有这个实例的,当时就没多想又对代码进行了检查然后加了判断,考虑可能是没获取到实例或者dom没渲染出来,因为前面的input是通过v-for循环的所以进行了更全面的判断代码如下所示

    focusNextInput(index) {
      console.log(`Trying to focus input-${index}`);
      const ref = this.$refs[`input-${index}`];
 this.$nextTick(() => {
             // 检查 ref 是否存在
      if (Array.isArray(ref) && ref.length > 0 && ref[0].focus) {
        ref[0].focus();  // 如果是数组形式,使用 ref[0] 并调用 focus
      } else if (ref && ref.focus) {
        ref.focus();  // 如果直接是 DOM 元素也调用 focus
      } else {
        console.error(`Reference for input-${index} not found or invalid`, ref);
      }
        });

    },

尝试方法2查看ref实例用ref上的方法

发现报错还是"TypeError: this.$refs["input-".concat(...)][0].focus is not a function"我就懵逼了。发现不是代码的问题,问题肯定是出现在了ref实例上,我就仔细的看ref实例里面的所有方法如下图所示
在这里插入图片描述
发现里没有focus()我想这一次可算找到根本了一次解决直接换成_focus()方法,发现是不报错了但是效果没有,我又换成_onFocus()方法发现也是不报错但是效果没有。到此时为止没有任何思路。

尝试方法3通过uniapp自带获取dom节点

中午吃了饭以后,我想为什么在uniapp中ref实例里面的方法不能用,那我通过uniapp自带的获取dom节点然后通过dom再去控制焦点,说干就干代码如下

    focusNextInput(index) {
		  console.log(`Trying to focus input-${index}`);
		  const ref = this.$refs[`input-${index}`];
		 if (ref && ref.length > 0) {
			// 使用微信小程序的API来设置焦点
			console.log(reg,'sssssssssssss')
			this.$nextTick(() => {
			  uni.createSelectorQuery().in(this).select(`#input-${index}`).fields({ node: true }).exec((res) => {
			      res[0].node._onFocus();  // 使用 focus 方法设置焦点
			  });
			});
		  } else {
			console.error(`Reference for input-${index} not found or invalid`, ref);
		  }
    },

我把这段代码修改后发现使用focus()还不行_focus()方法_onFocus()方法也不行

解决办法

上面我是所能用的方法都用了,这时候我想着看看官网吧,发现uniapp有自带的获取焦点的方法,只有用官网的方法才可以也就是<input :focus="focusState" @blur="dataExamine()"></input>这种,我心想那直接控制:focus实现代码如下所示:

<template>
  <view class="container">
    <view class="otp-container">
      <input
        v-for="(item, index) in otpLength"
        :key="index"
        type="tel"
		v-model="otpValues[index]"
		:focus="activeIndex === index"
        maxlength="1"
        @input="onInput($event, index)"
        @focus="onFocus(index)"
        :ref="`input-${index}`"
        :id="`input-${index}`"
        class="otp-input"
      />
    </view>
    <button @click="submitOTP">提交</button>
  </view>
</template>

<script>
export default {
  data() {
    return {
      otpLength: 5,          // 验证码的长度
      otpValues: ['', '', '', '', ''], // 存储每个输入框的值
      activeIndex: null      // 当前聚焦的输入框索引
    };
  },
  mounted() {
    // 页面加载完成时绑定 refs
    this.$nextTick(() => {
      console.log('Initial refs:', this.$refs);
    });
  },
  methods: {
    onInput(event, index) {
      const value = event.target.value;
      console.log(event, index, value,'1111111111111111111111111');
      this.$set(this.otpValues, index, value);  // 更新对应输入框的值

      if (value && index < this.otpLength - 1) {
        this.$nextTick(() => {
          this.focusNextInput(index + 1);  // 自动跳转到下一个输入框
        });
      }
    },
    onFocus(index) {
		this.activeIndex = index;  // 记录当前聚焦的输入框索引
		console.log(this.activeIndex);
    },
    focusNextInput(index) {
		console.log(`Trying to focus input-${index}`);
	    this.activeIndex = index;  // 设置指定输入框为焦点
    },
    submitOTP() {
      const otp = this.otpValues.join('');  // 将所有输入框的值拼接成一个字符串
      console.log('提交的验证码:', otp);  // 打印验证码
      // 这里可以添加提交验证码的逻辑
    }
  }
};
</script>

到此这个效果算是完成了,uniapp中有很多细节和vue上有偏差,还是需要熟读文档。还是那句话代码代码千千万,适合自己最重要。


http://www.kler.cn/a/397972.html

相关文章:

  • 计算机使用常用工具(持续更新)
  • Amazon Web Services (AWS)
  • 整数唯一分解定理
  • ADS项目笔记 1. 低噪声放大器LNA天线一体化设计
  • 【JAVA】使用IDEA创建maven聚合项目
  • 【CV】头盔检测区域入侵项目
  • docker启动训练容器教程
  • html数据类型
  • 【项目设计技巧】客户端SDK的开发
  • Linux驱动开发——pinctrl 和 和 gpio 子系统实验
  • 前缀和算法习题篇(上)
  • 【点云上采样】最近邻插值上采样算法 增加点云密度
  • C++ 编程基础(5)类与对象 | 5.8、面向对象五大原则
  • vue3中将在线url地址转为图片显示方法教程
  • RabbitMQ 通道(Channel)详解:方法使用、消息确认与拒绝
  • 零基础怎么开始学网络安全(非常详细)零基础入门到精通
  • Mac Java 使用 tesseract 进行 ORC 识别
  • [Qt] Qt删除文本文件中的某一行
  • springboot基于Web足球青训俱乐部管理后台系统开发(代码+数据库+LW)
  • 【SpringBoot】23 文件预览(kkFileView)
  • 前端传数组 数据库存Json : [1,2,3]格式
  • Bugku CTF_Web——文件上传
  • 19.UE5道具掉落
  • 【功耗现象】com.gorgeous.lite后台Camera 使用2小时平均电流200mA耗电量400mAh现象
  • 想租用显卡训练自己的网络?AutoDL保姆级使用教程(PyCharm版)
  • redis序列化数据查询