Vue3 接口数据赋值对象、渲染报错问题及解决
在Vue3中,我们通常使用 const
或 let
声明变量,将从接口(API)获取的数据赋值给对象进行渲染。但是,在应用程序开发中,当从API获取的数据不符合预期格式或不存在时,就可能会出现一些问题。在这篇文章中,我们将探讨这些问题,以及如何避免和解决它们。
问题描述
当我们从API获取到的数据不能完全符合我们的期望格式时,就可能会发生以下问题:
渲染报错:在模板中使用不存在的数据属性、从未定义的变量或未处理的空值可能会导致渲染错误。
未定义错误:尝试访问不存在的属性或方法时,将导致未定义的错误。
类型错误:类型错误通常是由于将错误类型的数据分配给对象而引起的。在Vue3中,此类错误的根本原因是因为类型检查严格执行了。
解决方案
为杜绝出现以上问题,我们应该在获取API数据之前明确期望的数据格式,对API的返回进行格式校验。
使用 interface
对返回数据进行格式校验
在TypeScript中,我们可以使用 interface
来定义对象的格式,进而进行数据校验。例如,假设我们有一个API:
interface ApiResponse {
id: number;
name: string;
age: number;
}
API返回的数据应该与 ApiResponse
接口一致,以避免后续的数据校验问题。
在具体的代码实现中,我们往往通过使用异步函数获取接口数据,如下:
async function fetchData() {
const response = await fetch('/api/data');
const data = await response.json();
// 校验获取的数据格式是否符合约定格式
if (!!data && !!data.id && !!data.name && !!data.age) {
// 数据符合格式,赋值给变量
const myData: ApiResponse = data;
// 将赋值后的对象传递给Vue组件进行渲染
createApp(App, { myData }).mount('#app');
} else {
// 如果数据格式不符合预期,我们就可以定义一个默认值并赋值给变量
const myData: ApiResponse = { id: 0, name: 'default', age: 0 };
// 将默认值传递给Vue组件进行渲染
createApp(App, { myData }).mount('#app');
}
}
在上述代码中,我们先通过 fetch
获取API数据,接着对数据进行格式校验,如果数据符合要求,则将数据赋值给 myData
对象并传递给Vue组件进行渲染。如果数据不符合我们的要求,则定义一个默认值(在这里值为 { id: 0, name: 'default', age: 0 }
),并将其传递给Vue组件进行渲染。
使用 try-catch
处理未定义错误
当我们尝试访问不存在的属性时,会出现未定义错误,这时我们可以使用 try-catch
语句来捕获该错误并处理它。例如:
try {
console.log(myData.noSuchProperty);
} catch (e) {
console.log('Property does not exist.');
}
在上述代码中,我们将尝试访问 myData
对象中不存在的属性 noSuchProperty
,如果访问失败,则 catch
捕获该错误并打印错误信息。
使用三元运算符解决类型错误
在Vue3中,类型检查严格执行了,当一个变量被分配为错误类型的数据时,将引发类型错误。为了解决这个问题,我们通常使用三元运算符。例如:
const myAge: number = typeof myData.age === 'number' ? myData.age : 0;
在上述代码中,我们先使用 typeof
判断 myData.age
是否是数字类型,如果是,则将其值分配给 myAge
;如果不是,则将 0
赋值给 myAge
。
示例说明
假设我们有一个API获取用户的数据,数据接口示例如下:
interface ApiResponse {
id: number;
name: string;
age: number;
}
示例1
首先,我们编写一个异步函数 fetchUserData
,用于获取API数据,并校验其格式是否正确。
async function fetchUserData(id: number) {
const response = await fetch(`/api/user/${id}`);
const data = await response.json();
if (!!data && !!data.id && !!data.name && !!data.age) {
return data;
} else {
return { id: 0, name: 'default', age: 0 };
}
}
在上述代码中,我们先通过 fetch
获取API数据,接着对数据进行格式校验,如果数据符合要求,则返回数据,否则返回 { id: 0, name: 'default', age: 0 }
。
接下来,我们创建一个Vue组件,用于将获取的数据进行展示:
<template>
<div>
<h2>{{ user.name }}</h2>
<p>Age: {{ user.age }}</p>
</div>
</template>
<script>
import { defineComponent, ref, watchEffect } from 'vue';
export default defineComponent({
props: {
userId: {
type: Number,
required: true,
},
},
setup(props) {
const user = ref<ApiResponse>({ id: 0, name: '', age: 0 });
watchEffect(async () => {
const data = await fetchUserData(props.userId);
user.value = data;
});
return {
user,
};
},
});
</script>
在上述代码中,我们通过 defineComponent
定义了一个Vue组件,该组件有一个 userId
属性,用于传递用户id。在 setup
函数中,我们定义了 user
变量,用于存储从API获取的用户数据。使用 watchEffect
监听 props.userId
,在该值发生变化时获取新的用户数据并更新 user
变量。
最后,我们将该组件渲染到页面中:
<template>
<div id="app">
<my-component :userId="3" />
</div>
</template>
<script>
import { createApp } from 'vue';
import MyComponent from './MyComponent.vue';
const app = createApp({});
app.component('my-component', MyComponent);
app.mount('#app');
</script>
在上述代码中,我们创建了一个Vue实例,并将组件 MyComponent
注册到该实例,然后将其挂载到DOM节点 #app
中。
示例2
在示例1中,我们仅仅是将非法数据替换为默认值,如果我们需要处理更为严重的错误,例如当API的返回状态码为 404 或 500 时,我们需要使用Catch语句来处理这些错误情况。修改 fetchUserData
函数,增加异常捕获处理:
async function fetchUserData(id: number) {
try {
const response = await fetch(`/api/user/${id}`);
if (!response.ok) {
throw new Error('API Error');
}
const data = await response.json();
if (!!data && !!data.id && !!data.name && !!data.age) {
return data;
} else {
throw new Error('Data Error');
}
} catch (e) {
console.error(e);
return { id: 0, name: 'default', age: 0 };
}
}
在上述代码中,我们使用 try-catch
语句捕获可能出现的异常,例如返回状态码非 200 的情况或数据格式不正确的情况。如果出现异常,则将错误信息打印到控制台,并返回默认值 { id: 0, name: 'default', age: 0 }
。
总结
在Vue3应用程序中,我们应该在获取API数据之前明确期望的数据格式,并对数据进行格式校验。如果数据不符合我们的要求,我们可以定义默认值或捕获异常来避免问题的出现。这些方法能够帮助我们在Vue3开发中规避类型检查的问题,提高代码的可读性和可维护性。