这是一个Laravel&Vue Js项目。一切都很好,但为什么我面临[Vue warn]:渲染错误:";TypeError:无法读取未定义的"的属性"name";类型错误。
我的Vue文件
<template>
<p>Sold By: {{product.user.name}}</p>
</template>
<script>
export default {
data(){
return {
product:{},
}
},
methods: {
loadData(){
axios.get('/api/'+this.$route.params.slug+'/product')
.then(response => {
this.product = response.data;
},
()=> {});
}
},
created(){
this.$Progress.start();
this.loadData();
this.$Progress.finish();
},
}
</script>
我的控制器
public function getProduct($slug)
{
$product = Product::where('slug',$slug)->with('brand','category','subCategory','productImages','featureDescriptions','colors','variants','user')->first();
return response()->json($product, 200);
}
``
Now I want to show my User name in Vue file <p>Sold By: {{product.user.name}}</p>. It showing User Name With an error [Vue warn]: Error in render: "TypeError: Cannot read property 'name' of undefined". when I show the user data <p>Sold By: {{product.user}}</p>, It show user all data without error. Now how i show user name without error.
错误不言自明:您在模板中使用{{product.user.name}}
。但是在product
从BE返回之前,product.user
是undefined
,因此不具有.name
属性。
最简单的修复方法是在<p>
:上放置v-if
<p v-if="product.user">Sold By: {{product.user.name}}</p>
这类问题的另一个通用解决方案是使用计算的
<template>
<p>Sold By: {{productUserName}}</p>
</template>
<script>
export default {
// ...
computed: {
productUserName() {
return this.product.user?.name || '';
}
}
// ...
}
</script>
您可以在这里阅读更多关于可选链接运算符(上面使用((?.
(的信息
因为它是JavaScript的一个新添加,Vue目前在<template>
标记中不支持它(但它在<script>
中有效(。
附加说明:一个常见的错误是添加一个额外的data
成员,而不是直接或通过computed
使用错误源(在这种情况下为product.user
(。这就产生了两个问题:
- 它将
product.user
与渲染<p>
解耦。这意味着,如果BE返回一个没有user
的product
,您仍然会得到错误,因为您已经将dataLoaded
设置为true
,但模板仍然试图读取user
的属性.name
,这是错误的,因此没有.name
- 您创建了不必要的样板:任何试图在以后理解或修改您的代码的人都必须弄清楚
dataLoaded
和product.user
之间的任意连接
Vue受欢迎的原因之一是它不需要样板代码,不像其他框架(例如:Angular(。保持这样!通过在模板中使用v-if="product.user"
,阅读该代码的人将立即理解呈现逻辑,而无需查看组件代码。如果你(或其他人(需要的话,减少定期计算代码所需的时间将大大减少修改代码的时间。这将产生更灵活、更可扩展的代码。更少的bug,花费更少的时间=>更多的钱。
之所以会发生这种情况,是因为<p>
正在渲染,而产品仍然是一个空对象(product: {}
(。
只有在产品已经加载的情况下,才能使用v-if
进行渲染。
<template>
<p v-if="dataLoaded">Sold By: {{ product.user.name }}</p>
</template>
<script>
export default {
data() {
return {
product: {},
dataLoaded: false,
};
},
methods: {
loadData() {
axios.get("/api/" + this.$route.params.slug + "/product").then(
(response) => {
this.product = response.data;
this.dataLoaded = true;
},
() => {}
);
},
},
created() {
this.$Progress.start();
this.loadData();
this.$Progress.finish();
},
};
</script>