Vue 切换输入框后需二次点击聚焦,如何定位光标到末尾
问题根因
当前实现无法达到预期,主要有三个明确的原因:
- 渲染时序不匹配:点击文本标签时,修改
editField的响应式值后,Vue会异步批量完成DOM更新,此时同步执行的聚焦逻辑,会碰到目标输入框还处于display: none的隐藏状态,无法触发有效聚焦。 - ref取值规则错误:原生DOM元素(input/textarea)的ref会直接绑定DOM节点本身,不需要额外取
.$el属性——.$el是Vue组件实例的专属属性,用来获取组件根DOM,用在原生元素上会得到undefined,自然无法调用focus方法。 - 缺少光标定位逻辑:就算聚焦成功,原生输入框聚焦后默认会将光标定位到文本开头,无法满足把光标移到已有内容末尾的需求。
可行解决方案
核心逻辑调整
利用Vue提供的$nextTick方法,等DOM完成「文本标签隐藏、输入框显示」的更新流程后,再执行聚焦和光标定位操作,具体实现步骤:
- 给所有需要编辑的表单元素绑定和字段名对应的动态ref,方便统一获取目标DOM
- 在
focusField方法中,设置完当前编辑字段后,等待下一DOM更新周期,再执行聚焦、光标定位操作
代码修改参考
模板部分调整
给两个表单元素补充对应字段的ref,移除冗余的focus事件绑定:
<div class="input-container"> <h3 class="field-value" v-show="!showField('name')" @click="focusField('name')">{{ user.name }}</h3> <input v-model="user.name" v-show="showField('name')" type="text" ref="field_name" class="field-value form-control" @blur="blurField" > </div> <div class="input-container"> <h3 class="field-value" v-show="!showField('email')" @click="focusField('email')">{{ user.email }}</h3> <textarea name="testing" cols="30" rows="10" v-model="user.email" v-show="showField('email')" type="email" ref="field_email" class="field-value form-control" @blur="blurField" ></textarea> </div>
方法部分调整
修改focusField逻辑,补充聚焦和光标定位的实现,删除冗余的hi方法:
data() { return { user: { name: pa.data.text1, email: pa.data.text2 }, editField: '', } }, methods: { focusField(name) { this.editField = name; // 等待DOM更新完成,此时输入框已经从隐藏状态变为可见 this.$nextTick(() => { // 通过ref规则拼接获取对应的DOM元素 const targetElement = this.$refs[`field_${name}`]; if (!targetElement) return; // 触发聚焦 targetElement.focus(); // 将光标定位到已有内容的末尾 const contentLength = targetElement.value.length; targetElement.setSelectionRange(contentLength, contentLength); }) }, blurField() { this.editField = ''; }, showField(name) { return (this.user[name] == '' || this.editField == name) } }
效果说明
按照上述逻辑调整后,点击文本标签时会自动完成输入框显示、聚焦、光标移到内容末尾的全流程操作,不需要用户二次点击输入框,同时保留原有的失焦切回文本标签的交互逻辑。
注:
setSelectionRange方法同时适配单行input和多行textarea,不需要单独编写两类元素的光标定位逻辑。
内容的提问来源于stack exchange,提问作者Pavle Ilic
相关产品推荐
相关产品推荐

