【问题标题】:Infinite repeated while using v-for in vuejs在 vuejs 中使用 v-for 时无限重复
【发布时间】: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>  

【问题讨论】:

    标签: javascript vue.js vuejs2 v-for


    【解决方案1】:

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

    我能想到两种解决方案:

    1. td 上使用 v-once 指令。该指令防止在初始渲染后进一步更新元素。
    <td v-once> {{ getAuthor(item.authorId) }}</td>
    
    1. 在获取图书数据时填充作者(也可以在 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
    猜你喜欢
    • 2020-10-21
    • 2020-01-31
    • 1970-01-01
    • 2020-04-22
    • 2019-09-13
    • 1970-01-01
    • 2020-09-08
    • 2019-08-19
    • 2018-04-27
    相关资源
    最近更新 更多