在 vuejs 中使用 v-for 时无限重复

Posted

技术标签:

【中文标题】在 vuejs 中使用 v-for 时无限重复【英文标题】:Infinite repeated while using v-for in vuejs 【发布时间】:2021-10-05 04:41:33 【问题描述】:

我有一个获取书籍列表的 API,在每本书中我都有作者 ID。 我还想通过另一个 API(获取作者)从该 ID 获取作者姓名,所以我使用 v-for 来获取书籍列表中的项目。我调用 getAuthor(authorId) 函数的每个项目,但它会无限重复。有谁知道是什么原因? 我的源代码:

export default   
name: 'GetBooks',  
    data() 
        return 
            books: [],
            categories: [],
            author: [],
        ;
    ,
    created()  
      
        this.getBooks();  
    ,  

methods:  
    getBooks()   
        BookServices.getBooks().then(response =>   
                this.books = response.data;  
                console.log(response.data);  
            )  
            .catch(e =>   
                console.log(e);  
            );  
    ,  
    getAuthor(id)   
        BookServices.getAuthor(id).then(response =>   
                this.author = response.data.name;
                console.log(response.data.name);  
            );
        return this.author;
    ,  
  

与:

<tbody>  
    <tr v-for="item in books" :key="item.id">  
        <td> item.id </td>  
        <td> item.name </td>  
        <td> getAuthor(item.authorId) </td>  
        <td> item.price </td>  
        <td> item.year </td>   
        <td><input class='myclass' type='button' value='Detail'/></td>
    </tr>  
</tbody>  

【问题讨论】:

【参考方案1】:

问题是每次调用getAuthor 都会触发一次模板重新渲染,这反过来又会触发对getAuthor 的新调用,从而导致无限调用。

我能想到两种解决方案:

    td 上使用 v-once 指令。该指令防止在初始渲染后进一步更新元素。
<td v-once>  getAuthor(item.authorId) </td>

    在获取图书数据时填充作者(也可以在 API 中完成)。

     getBooks()   
         BookServices.getBooks().then(response =>   
                 this.books = response.data;
    
                 this.books = this.books.map(book => 
                     book["author"] = this.getAuthor(book.authorId)
                     return book
                 )  
    
             )  
             .catch(e =>   
                 console.log(e);  
             );  
     ,  
    

然后,在模板中引用作者:

<tr v-for="item in books" :key="item.id">  
    <td> item.id </td>  
    <td> item.name </td>  
    <td> item.author </td>  
    <td> item.price </td>  
    <td> item.year </td>   
    <td><input class='myclass' type='button' value='Detail'/></td>
</tr>  

【讨论】:

非常感谢!正如你所说,每次调用 getAuthor 都会触发一次模板重新渲染,这就是它有无限调用的原因。非常感谢@IgorMoraru【参考方案2】:

模型获取方法应该决定何时以及如何获取作者,而不是标记。 (这是@IgorMoraru 的第二个好主意,已更正以正确处理作者的异步获取)。

这也修复了将书籍作者分配给视图实例的 OP 代码错误。

getBooks()   
    BookServices.getBooks().then(response =>   
            this.books = response.data;  
            console.log(response.data);
            this.getAuthors();  
        )  
        .catch(e =>   
            console.log(e);  
        );  
,
getAuthors() 
  let promises = this.books.map(book => this.getAuthor(book));
  return Promise.all(promises);
,
getAuthor(book)   // note the change: pass the book here, not the id
    BookServices.getAuthor(book.id).then(response =>   
            book.author = response.data.name;
            console.log(response.data.name);  
        );
    return this.author;
,  

保护(暂时)缺少作者的书籍的标记...

    <td> item.id </td>  
    <td> item.name </td>  
    <td v-if="item.author"> item.author </td>
    <td v-else>fetching...</td>
    <td> item.price </td>  
    <td> item.year </td>   

【讨论】:

您的解决方案对我帮助很大!我成功修复了?@danh

以上是关于在 vuejs 中使用 v-for 时无限重复的主要内容,如果未能解决你的问题,请参考以下文章

解决vuejs无限死循环 - createdmounted重复不断执行

解决vuejs无限死循环 - createdmounted重复不断执行

解决vuejs无限死循环 - createdmounted重复不断执行

Vuejs - 如何使用 v-for 获取数组中的所有唯一值(删除重复项)

在 laravel 中对数据数组进行分页并在 vuejs 中使用无限滚动的最佳方法

使用无限滚动时在我的表格视图中重复数据