Vue 3中nextTick()结合焦点Ref使用问题:textarea自动聚焦报错
问题分析与解决方案
你遇到的错误核心原因是元素ref与数据ref命名冲突,加上错误地覆盖了ref引用,导致content.value不是DOM元素而是字符串,自然无法调用focus()方法。具体问题和修复步骤如下:
1. 解决ref命名冲突
你同时把textarea的ref设为content,又用const content = ref('')作为v-model的绑定变量,这会导致两者混淆。Vue3中,元素ref指向的是DOM元素对象,而数据ref是响应式字符串,重名后会相互覆盖,最终content指向的是数据变量而非DOM元素。
修复:给元素ref和数据变量起不同的名字,比如把元素ref改为contentRef,数据变量保留content。
2. 修正ref引用的赋值方式
在openingHTMLEmbedder事件回调里,你直接用content = data.content,这会把原本的响应式ref对象替换成普通字符串,彻底丢失DOM元素的引用。正确的做法是修改ref的.value属性。
同样,existingBlot = data.existingBlot也是错误的,应该改为existingBlot.value = data.existingBlot。
3. 确保在DOM渲染完成后调用focus
要先执行modalShown.value = true让textarea渲染到DOM中,再借助nextTick等待DOM更新完成后调用focus。
修改后的完整代码:
<textarea ref="contentRef" cols="30" rows="10" class="input" placeholder="Paste your HTML here" v-model="content"> </textarea> <script setup> import { nextTick, onMounted, ref } from 'vue'; const modalShown = ref(false); const existingBlot = ref(null); const content = ref(''); const contentRef = ref(null); const applyHTML = () => { emit('adding', { content: content.value, existingBlot: existingBlot.value, }); close(); } const close = () => { modalShown.value = false; content.value = ''; existingBlot.value = null; } onMounted(() => { emitter.on('openingHTMLEmbedder', async (data) => { if (data) { content.value = data.content; existingBlot.value = data.existingBlot; } modalShown.value = true; await nextTick(); contentRef.value?.focus(); }); }); </script>
额外注意点:
- 传递数据给父组件时,要传
content.value而非content(ref对象),否则父组件拿到的是响应式对象而非实际值。 - 使用
contentRef.value?.focus()的可选链操作符,可以避免模态框未渲染时contentRef.value为null的报错。
内容的提问来源于stack exchange,提问作者Bhazk
相关产品推荐
相关产品推荐

