Я попытался получить данные из API с параметрами, которые исходят из аргумента в v-for.
В методе findUser
я могу console.info
получить данные, которые ищу. Но я не могу получить это в конце findUser
, почему?
Я знаю, что есть способ async
получить его, но я не понимаю, как им управлять, чтобы он работал с тем, что я хочу делать;
Я тоже думал вызвать два API одновременно, но результат тот же, не знаю как с этим справиться.
<template>
<div>
<h4>Listes Reçues</h4>
<p v-for = "element in results" id = "flex-list" :key = "element.list_id">
{{ element.list_name }} de {{ findUser(element.user_id) }}
</p>
</div>
</template>
<script>
export default {
data() {
return {
results: '',
nickname: '',
}
},
created() {
this.$axios
.get(`/api/listReceived/${this.$auth.user[0].user_id}`)
.then((res) => {
this.results = res.data
console.info(JSON.stringify(this.results))
})
.catch((err) => {
console.error(err)
})
},
methods: {
findUser(id) {
console.info(id)
let data = ''
this.$axios
.get(`http://localhost:3000/api/userdata/${id}`)
.then((res) => {
data = res.data[0].nickname
console.info(data)
})
.catch((err) => {
console.error(err)
})
return data
},
},
}
</script>
created()
отлично работает с Vue, но обычно вы используете хуки fetch()
и asyncData()
в Nuxt.
Вот основная идея использования API заполнителя JSON.
Вот возможно /pages/index.vue
<template>
<div class = "flex flex-col items-center">
<h1 class = "p-4 bg-green-700 rounded-md">
List of users from JSONplaceholder
</h1>
<section class = "mt-4">
<p v-for = "user in users" :key = "user.id">
{{ user.name }} ? {{ user.email }} ~
<nuxt-link
:to = "{ name: 'users-id', params: { id: user.id } }"
class = "border-b-4 border-green-500"
>
Check details
</nuxt-link>
</p>
</section>
</div>
</template>
<script>
export default {
name: 'Index',
data() {
return {
users: [],
}
},
async fetch() {
this.users = await this.$axios.$get('/users')
},
}
</script>
<style>
* {
@apply bg-gray-800 text-gray-100;
}
</style>
И подробная страница, также известная как /pages/users/_id.vue
, с использованием fetch()
крючок.
<template>
<div class = "flex flex-col items-center">
<nuxt-link class = "p-4 bg-purple-700 rounded-md" :to = "{ name: 'index' }">
Go back
</nuxt-link>
<h2>User details ID: # {{ $route.params.id }}</h2>
<p v-if = "$fetchState.pending">Loading user's info...</p>
<p v-else-if = "$fetchState.error">Error while fetching user</p>
<div v-else>
<p>{{ user.name }}</p>
<p>{{ user.phone }}</p>
<p>{{ user.website }}</p>
<p>{{ user.company.name }}</p>
</div>
</div>
</template>
<script>
export default {
name: 'UserId',
data() {
return {
user: {},
}
},
async fetch() {
this.user = await this.$axios.$get(`/users/${this.$route.params.id}`)
},
}
</script>
Я предпочитаю этот подход, потому что он не блокирует рендеринг, вы можете добавить немного гладкий скелет, чтобы пользователь знал, что что-то происходит. Кроме того, fetch()
доступен как для компонентов, так и для страниц, а asyncData()
— только для страниц.
Это также дает хороший $fetchState
помощник, который также может быть очень удобным!
Вот та же /pages/users/_id.vue
страница с использованием asyncData() hook
.
<template>
<div class = "flex flex-col items-center">
<nuxt-link class = "p-4 bg-purple-700 rounded-md" :to = "{ name: 'index' }">
Go back
</nuxt-link>
<p>{{ user.name }}</p>
<p>{{ user.phone }}</p>
<p>{{ user.website }}</p>
<p>{{ user.company.name }}</p>
</div>
</template>
<script>
export default {
name: 'UserId',
async asyncData({ route, $axios }) {
const user = await $axios.$get(`/users/${route.params.id}`)
return { user }
},
}
</script>
Основным преимуществом использования asyncData
является тот факт, что он более безопасен и блокирует рендеринг (может быть как за, так и против, лично для меня скорее минус).
Вот несколько другие подробные ответы, сравнивающих fetch()
и asyncData()
.
Посмотрите этот удобная статья в блоге по этому вопросу, а также этот Пример клонирования dev.to.
Наконец, если вы хотите пойти по пути SSG и оптимизировать все это с наименьшим количеством вызовов API один раз на стороне клиента, вы также можете проверить мой другой ответ.
В дополнение к моему главному ответу, который был совершенно не по теме вопроса, но все же актуален, вот пример того, как правильно обрабатывать перекресток.
Я не использовал конечную точку, а издевался над данными локально в data()
, поэтому я сохраняю свой пост выше.
<template>
<div class = "flex flex-col items-center">
<h1 class = "p-4 bg-green-700 rounded-md">
List of users ordered by their according message
</h1>
<!-- <pre>{{ messages }}</pre> -->
<section>
<div v-for = "user in groupedMessages" :key = "user.id" class = "mt-4">
<p>
User: <b>{{ user.name }}</b>
</p>
<aside>
Messages:
<span v-if = "!user.messages.length">No messages actually</span>
</aside>
<p v-for = "message in user.messages" :key = "message.id">
<span class = "italic">- {{ message.text }}</span>
</p>
</div>
</section>
</div>
</template>
<script>
// ES version of lodash, lighter overall
import { cloneDeep } from 'lodash-es'
export default {
name: 'Index',
data() {
return {
messages: [
{
id: 1,
text: 'Hello world',
userId: 1,
},
{
id: 2,
text: 'Nice cool message',
userId: 1,
},
{
id: 3,
text: 'Still for the first user?',
userId: 1,
},
{
id: 4,
text: 'Yep, apparently...',
userId: 1,
},
{
id: 5,
text: "Eh, surprise, I'm a sneaky one...",
userId: 3,
},
{
id: 6,
text: 'Oh, a second one.',
userId: 2,
},
{
id: 7,
text: "You're damn right!!",
userId: 2,
},
],
users: [
{
name: 'Patrick',
id: 1,
messages: [],
},
{
name: 'Pablo',
id: 2,
messages: [],
},
{
name: 'Unkown author',
id: 5,
messages: [],
},
{
name: 'Escobar',
id: 3,
messages: [],
},
],
}
},
computed: {
groupedMessages() {
// we use that to avoid any kind of further mutation to the initial `users` array
const clonedUsers = cloneDeep(this.users)
// we do loop on each message and find a corresponding user for it
this.messages.forEach((message) =>
clonedUsers.forEach((user) => {
if (user.id === message.userId) {
user.messages.push(message)
}
})
)
return clonedUsers
},
},
}
</script>
репозиторий на гитхабе доступен, пожалуйста, не обращайте внимания на несвязанное имя.
Вот так выглядит на Netlify.