在 vuejs 中使用 v-for 时无限重复
Infinite repeated while using v-for in vuejs
我有一个 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>
问题是每次调用 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>
模型获取方法应该决定何时以及如何获取作者,而不是标记。 (这是@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>
我有一个 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>
问题是每次调用 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>
模型获取方法应该决定何时以及如何获取作者,而不是标记。 (这是@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>