如何在 Nuxt 中的 2 个数据集之间建立交集?

How to make an intersection between 2 datasets in Nuxt?

我试图从 api 获取数据,其中的参数来自 v-for 中的参数。 在 findUser 方法中,我可以 console.log 我正在寻找的数据。但是我在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.log(JSON.stringify(this.results))
      })
      .catch((err) => {
        console.error(err)
      })
  },
  methods: {
    findUser(id) {
      console.log(id)
      let data = ''
      this.$axios
        .get(`http://localhost:3000/api/userdata/${id}`)
        .then((res) => {
          data = res.data[0].nickname
          console.log(data)
        })
        .catch((err) => {
          console.error(err)
        })
      return data
    },
  },
}
</script>

created() 在 Vue 中完全没问题,但通常你会在 Nuxt 中使用 fetch()asyncData() 钩子。
这是使用 JSONplaceholder's API.

的基本思想

这是一个可能的/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() 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>

    <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>

我确实更喜欢这种方法,因为它不会阻塞渲染,您可以添加一些 smooth skeleton 以仍然让用户知道正在发生某些事情。最重要的是,fetch() 在组件和页面上都可用,而 asyncData() 仅适用于页面。
它还提供了非常方便的 $fetchState helper


这是使用 asyncData() hook 的相同 /pages/users/_id.vue 页面。

<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()
看看这个 handy blog article on the subject and also this dev.to clone example.


最后,如果您想采用 SSG 路径并在 client-side 上以最少的 API 调用次数优化整个过程,您还可以检查

除了我的最佳答案之外,这个问题与问题无关但仍然相关,这里有一个关于如何正确处理交叉路口的示例。

我没有使用端点,而是在 data() 中本地模拟了数据,因此我将 post 保留在上面。

<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>

github repo is available中的无关名称请不要关注

这是它的样子 on Netlify