渲染组件后如何关注特定的输入文本?

Posted

技术标签:

【中文标题】渲染组件后如何关注特定的输入文本?【英文标题】:How to focus on a specific input text after the component is rendered? 【发布时间】:2020-04-18 23:13:33 【问题描述】:

每次渲染组件时,我都在努力使其正常工作即使我为索引传递了另一个值。基本上,我将一个索引值传递给了输入文本元素的 ref,它位于组件的 v-for 循环内,所以在mounted(),我有一些东西像这样

mounted() 
  this.$nextTick(() => 
                  
      this.$refs.newInp[index].focus();          
    );
  

但即使我传递了 1 或 2 的值,它仍然专注于第一个输入元素。当我查看控制台日志时,它会在控制台上显示此错误。 TypeError:无法读取未定义的属性“0” 指向这条线this.$refs.newInp[index].focus();

获取 v-for 中数据的示例代码

async GetContentDetails() 
     let testRes =
         await axios.get('myUrl/api', 
              params: 
                   ContentId: this.$cookie.get('OpV-ContId')
                      
                 ).then(res => this.contentItems = res.data)
                      .then()
                      .catch(error => console.log(error));
                this.testData = testRes;

模板:

<div v-for="(contItem, index) in contentItems" :key="contItem.commentId">
  <textarea class="reply-commented" ref="newInp"></textarea>
  </div>

如何解决此类问题?解决方案是什么? 谢谢。

【问题讨论】:

放最少的代码来理解 @Rahul - 你还需要什么代码?那是我曾经关注的唯一代码。你不明白哪一部分? 您的 v-for 循环数据是异步获取的,因为在这种情况下,输入字段将在获取数据后创建,并且在挂载的钩子中无法访问该字段,因此出现错误。如果没有,你能用小提琴重现它吗? newInp 未定义。也许是v-if 或类似的东西。我们可以看看模板吗? @Himanshu - 是的,在 v-for 循环中获取的数据使用异步,就像这个异步 GetContentDetails() let testRes = await axios.get('myUrl/api', params : ContentId: this.$cookie.get('OpV-ContId') ).then(res => this.contentItems = res.data) .then() .catch(error => console.log(error) ); this.testData = testRes; 【参考方案1】:

据我了解,您想在获取一些数据后关注 textarea,这表示尝试在 mounted 方法内关注将不起作用,因为您无法判断数据是否已被提取,而 @987654323 @s 已经存在于 DOM 中。

因此,最好的方法是在确定数据已被获取后,在 then 回调中关注。

new Vue(
  el: '#app',
  
  data: 
    posts: [],
    index: 3 // Change this to focus whatever textarea you want
  ,
  
  mounted () 
    this.fetchItems();
  ,
  
  methods: 
    fetchItems () 
      const url = 'https://jsonplaceholder.typicode.com/posts'

      axios.get(url).then(response => 
        this.posts = response.data
        
        this.$nextTick(_ => 
          this.$refs.newInp[this.index].focus()
        )
      )
    
  
);
<div id="app"> 
  <div v-for="(post, index) in posts" :key="post.id">
    <textarea class="reply-commented" ref="newInp" v-text="post.body"></textarea>
  </div> 
</div>



<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

【讨论】:

仍然需要测试获取的列表是否为空。 是的。您可以测试模板级别或回调内部是否有项目 @HelderLucas ...这与我使用的代码相同,但问题是它始终关注索引 = 0 处的第一个元素。尝试将索引更改为另一个值,例如 1 或2 我打赌仍然会专注于 index = 0。尝试自己测试一下。 代码 sn-p 的输出正是我所关注的问题。它将始终聚焦在 index = 0。 @HelderLucas - 抱歉回复晚了......嗯,我的结果很糟糕......这不是焦点的行为,可能是因为我正在从服务器获取我的数据数据库。将数据绑定到组件中可能存在延迟问题,但无论如何我会考虑您的答案,我会为此给出一个观点......非常感谢您的帮助。我非常感激。有一个好伙伴!【参考方案2】:

为了几天的研究和彻底的测试和观察关于 vue.js 如何渲染组件的 DOM 行为,当然也是基于其他人在这个线程上的建议。我意识到你不能真正专注于 for 循环中元素的特定索引上的创建/安装属性,特别是在这种情况下,如果要获取数据以绑定到组件上,则输入文本元素由于其异步行为,它来自服务器,您必须等到组件完全呈现。所以我至少在我的情况下找到了一个解决方案,在创建或安装的属性中使用动态观察器,并为数据属性的默认更改设置一个虚拟或重复的数据属性,目的只是为了激活观察器以专注于组件渲染后的特定元素。这是它的样子。希望这对遇到与我相同情况的人有所帮助。

created()            
            this.GetContentDetails();
            this.$watch('commentItems2', function () 
                this.$nextTick(() => 
                    this.$refs.newRep[mapCredential.state.index2].focus();
                );
            );
        ,

methods: 
 async GetComment2() 
                let testRes =
                    await axios.get('myUrl/api/GetContent/GetComments')
                        .then(this.GetReply2())
                        .catch(error => console.log(error));
                this.commentItems = testRes.data;
                this.commentItems2 = testRes.data;
            ,

【讨论】:

以上是关于渲染组件后如何关注特定的输入文本?的主要内容,如果未能解决你的问题,请参考以下文章

渲染power-select-multiple后如何关注输入?

渲染后如何在输入字段上设置焦点?

页面加载后如何触发对 WebView 中文本输入字段的关注?

在React中提交表单后如何取消对输入的关注

Sencha Touch:如何以编程方式关注 ios 上的文本字段?

如果验证失败,如何关注错误的文本字段