Vue组件props类型不匹配求助:categoryId期望Number却得到String
问题:Vue组件Props类型不匹配错误
错误信息:
Invalid prop: type check failed for prop "categoryId". Expected Number with value 13, got String with value "13"
将CategoryShow组件的categoryId props类型从String改为Number后出现该错误,此前String类型可正常运行。CategoryHome是CategoryShow的父组件,在CategoryHome中console.log(typeof categoryId)输出为number,但CategoryShow接收的props类型却不匹配,请问代码哪里出错了?
相关代码
CategoryShow.vue
<script setup> import axios from "axios"; import { ref, watch} from "vue" import { useRoute, useRouter } from 'vue-router' const route = useRoute() const router = useRouter() const props = defineProps({ categoryId: { //type: String, type: Number } }) const categories = ref([]) const singleCategory = ref({}) const recipes = ref([]) const getCategory = () => { return axios.get('/api/categories/' + props.categoryId) } const getCategories = () => { return axios.get('/api/categories') } const getRecipes = () => { return axios.get('/api/categories/' + props.categoryId + '/recipes/') } const getCategoriesAndCategoryAndRecipes = async () => { const res1 = await getCategories() const res2 = await getCategory() const res3 = await getRecipes() singleCategory.value = res2.data recipes.value = res3.data categories.value = res1.data } // 组件创建时调用 getCategoriesAndCategoryAndRecipes() // 监听路由变化 watch(route, () => { if (!isNaN(props.categoryId)) { getCategoriesAndCategoryAndRecipes() } }) </script> <template> <div class="left-container"> <div class="form-box"> <h4 style="margin-bottom: 20px; margin-top: 10px">RECIPE HOUSE</h4> <form method="post" v-on:submit.prevent="addCategory"> <input type="text" v-model="newCategory"> </form> </div> <ul class="category_ul"> <li v-for="category in categories" :key="category.id"> <button class="btn btn-danger" v-on:click="deleteCategory(category.id)">Delete</button> <router-link :to="{name: 'category.show', params: {categoryId: category.id }}"> <span>{{ category.title }}</span> </router-link> </li> </ul> </div> <div class="right-container"> <span class="icon"> <i class="fas fa-utensils fa-lg"></i> </span> <div> <span>{{ singleCategory.title }}</span> <form method="post" v-on:submit.prevent="addRecipe"> <input type="text" v-model="newRecipe"> </form> <ul style="margin-top: 15px;"> <li v-for="recipe in recipes"> <router-link :to="{name: 'recipe.show', params: {recipeId: recipe.id}}"> <span>{{ recipe.title }}</span> </router-link> </li> </ul> </div> </div> </template>
CategoryHome.vue
<script setup> // import axios from "axios" import { onMounted, ref } from "vue" import { useRouter } from 'vue-router' const router = useRouter() const newCategory = ref('') let categoryId = '' async function initial() { try { const res = await axios.get('/api/max') categoryId = res.data.id console.log(typeof categoryId) // 输出number router.push({name: 'category.show', params: { categoryId: categoryId }}) } catch(err) { console.log('error handling') } } initial() </script> <template> <div class="left-container"> <h4 style="margin-bottom: 20px; margin-top: 10px">RECIPE HOUSE</h4> <form method="post" v-on:submit.prevent="addCategory"> <input type="text" v-model="newCategory"> </form> </div> </template>
解决方案
问题根源:Vue Router的路由参数默认会被转换为字符串类型,哪怕你传入的是数字,最终通过路由传递到组件的参数都会变成字符串,这就导致CategoryShow组件接收的categoryId是字符串,和你定义的Number类型props不匹配。
解决方法1:在路由定义中自动转换参数类型
找到你的路由配置文件(通常是router/index.js),给category.show路由添加props配置,将参数转为数字:
const routes = [ // ...其他路由 { name: 'category.show', path: '/categories/:categoryId', component: () => import('../views/CategoryShow.vue'), // 这里将路由参数转为Number类型 props: route => ({ categoryId: Number(route.params.categoryId) }) } ]
解决方法2:在组件内部兼容类型并转换
如果不想修改路由配置,可以修改CategoryShow的props定义,允许接收字符串或数字,然后在内部转为数字使用:
const props = defineProps({ categoryId: { type: [Number, String], // 允许两种类型 required: true } }) // 在使用时转为数字 const numericCategoryId = Number(props.categoryId) // 修改接口请求的地方,用转换后的数字 const getCategory = () => { return axios.get('/api/categories/' + numericCategoryId) } const getRecipes = () => { return axios.get('/api/categories/' + numericCategoryId + '/recipes/') }
额外优化:修正watch中的判断逻辑
原代码中!isNaN(props.categoryId)的判断存在问题,因为字符串"13"传入isNaN会被隐式转为数字,返回false,导致判断失效。可以改成:
watch(route, () => { const id = Number(props.categoryId) if (!isNaN(id)) { getCategoriesAndCategoryAndRecipes() } })
内容的提问来源于stack exchange,提问作者sora sakamoto
相关产品推荐
相关产品推荐

