使用Vue Composition API(script setup)的Fetch API

huangapple go评论126阅读模式
英文:

Fetch API with Vue Composition API (script setup)

问题

以下是您要翻译的内容:

我感到非常困惑。我想要一个简单的通用获取函数来学习基础知识,但我想要在Vue Composition API和脚本设置中执行它。

这是我的脚本:


这是我的模板:


```

我收到的错误:

TypeError: Cannot read properties of null (reading 'activity')

我收到的 JSON 数据:

{
    "activity": "制作自己的乐高创作",
    "type": "娱乐",
    "participants": 1,
    "price": 0,
    "link": "",
    "key": "1129748",
    "accessibility": 0.1
}

就是这么简单... 在整个互联网上,我找不到一个关于脚本设置、Fetch API和显示值的解决方案。

但最令人困惑的是:它显示了该值!那么为什么会出现这个错误?


<details>
<summary>英文:</summary>

I am so confused. I want a simple generic fetch function to learn it on basic, but I want to do it with the Vue Composition API and script setup. 

This is my script:

<script setup>
import {ref} from 'vue';

const boredInfo = ref(null)

function theData(url) {
fetch(url)
.then(response => response.json())
.then(actualData => {
console.log(actualData)
boredInfo.value = actualData
})
.catch((e) => {
console.error('Das ist der Catch Error: ', e)
})

return boredInfo
}

theData('https://www.boredapi.com/api/activity')

</script>


This is my template

<template>
<h1>Lets go!</h1>
<div>
<h1>Aktivität: {{boredInfo.activity}}</h1>
</div>
</template>


Error I get:

ypeError: Cannot read properties of null (reading 'activity')


JSON I get

{
"activity": "Make your own LEGO creation",
"type": "recreational",
"participants": 1,
"price": 0,
"link": "",
"key": "1129748",
"accessibility": 0.1
}


As simple as that... In the whole internet I cannot find a solution for script setup, Fetch API and display the value.
 
But the most confusing: It shows the value! So why this error?

</details>


# 答案1
**得分**: 1

问题在于在你的数据获取完成之前,你尝试访问 `boredInfo.activity`,而此时 `boredInfo` 仍然只是 `ref(null)`。

要么在初始化时使用预期的结构,即:
```javascript
const boredInfo = ref({activity: null})

要么在访问之前避免过早访问,可以使用 v-if、表达式中的三元运算符、可选链 (?.) 等等。像这样:

<h1 v-if="boredInfo !== null">活动: {{boredInfo.activity}}</h1>

你也可以在加载时显示一个加载中的旋转图标,这样会更友好。

英文:

The problem is that you are accessing boredInfo.activity before your fetch has finished, when boredInfo is still just ref(null).

Either initialize it with the expected structure, i.e.

const boredInfo = ref({activity: null})

or avoid a premature access with v-if, a ternary in the expression, optional chaining (?.), etc. Something like:

&lt;h1 v-if=&quot;boredInfo !== null&quot;&gt;Aktivit&#228;t: {{boredInfo.activity}}&lt;/h1&gt;

You can show a loading spinner while loading, that's always nice.

答案2

得分: 1

我想解释为什么会出现错误 Cannot read properties of null (reading 'activity')

首先,当组件挂载时,您尝试访问一个不存在的属性,activity 属性在 boredInfo 对象内并不存在,因此在组件渲染时,不会有任何预期加载该属性的内容。

我们可以通过两种方式来解决这个问题,第一种方式非常简单,将属性名称添加到 const boredInfo = ref() 内,如下所示:

const boredInfo = ref({
  activity: ''
});

这个设置将绕过错误。

另一种选择是在数据尚未加载时添加加载状态,这意味着它将等待我们的 theData 方法解析,首先定义一个新的变量来指示加载状态:

const isLoading = ref(true);

然后,我们将使用异步/等待来等待 fetch 方法生成的 Promise,然后将加载值更改为 false,因为所有数据都将被加载:

async function theData(url) {
  try {
    isLoading.value = true;
    const response = await fetch(url);
    const actualData = await response.json();
    boredInfo.value = actualData;
  } catch (e) {
    console.error('这是 Catch 错误:', e);
  } finally {
    isLoading.value = false;
  }
}

然后,我们配置我们的模板,使用 v-if 等待 isLoading 变为 false,以显示 API 的返回值:

<template>
  <h1>让我们开始吧!</h1>
  <div v-if="!isLoading">
    <h1>活动: {{ boredInfo.activity }}</h1>
  </div>
</template>

就是这样,就完成了!

您可以在 这里 查看实际示例。

英文:

I would like to explain why you are getting the error Cannot read properties of null (reading &#39;activity&#39;)

First of all, you're trying to access a property that doesn't exist when the component is mounted, the activity property doesn't exist inside boredInfo object, so when the component is rendered it will not expect anything to want to load that property.

we can fix this in 2 ways, the first way is very simple, add the property name inside const boredInfo = ref(), something like this:

const boredInfo = ref({
  activity: &#39;&#39;
});

This setting will bypass the error.

The other option is to add a loading while the data is not yet loaded, that means that it will wait for our theData method to resolve, firstly a new variable is defined that will indicate the loading status:

const isLoading = ref(true);

Then we will use async/await to wait for the promise that the fetch method generates, and then change the load value to false, since all the data will be loaded:

async function theData(url) {
  try {
    isLoading.value = true;
    const response = await fetch(url);
    const actualData = await response.json();
    boredInfo.value = actualData
  } catch(e) {
    console.error(&#39;Das ist der Catch Error: &#39;, e)
  } finally {
    isLoading.value = false;
  }
};

And then we configure our template with a v-if to wait for isLoading to be false, to display the return value of the api:

&lt;template&gt;
	&lt;h1&gt;Lets go!&lt;/h1&gt;
  &lt;div v-if=&quot;!isLoading&quot;&gt;
    &lt;h1&gt;Aktivit&#228;t: {{ boredInfo.activity }}&lt;/h1&gt;
  &lt;/div&gt;
&lt;/template&gt;

And there you have it, that's it!

You can see the live example here

答案3

得分: 0

I think you forget that the code below :

<template>
  <h1>Let's go!</h1>
  <div>
    <h1>Activity: {{boredInfo.activity}}</h1>
  </div>
</template>

It has called before your API call is done. So... the simple solution is you can add v-if inside the div or h1 to check if the variable has been filled by the API response. That's the main problem, so the solution can be more varied depending on yours.

英文:

I think you forget that the code below :

&lt;template&gt;
 &lt;h1&gt;Lets go!&lt;/h1&gt;
 &lt;div&gt;
  &lt;h1&gt;Aktivit&#228;t: {{boredInfo.activity}}&lt;/h1&gt;
 &lt;/div&gt;
&lt;/template&gt;

It has called before your api call is done. so... the simple solution is you can add v-if inside the div or h1 to check is variable has filled by the api response. Thats the main problem, so the solution it can be more variety depends yours.

huangapple
  • 本文由 发表于 2023年3月10日 00:04:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/75687152.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定