我通过实施一个简单的购物车来学习一些VueJS。
这是我的HTML:
<div id="app">
<table>
<thead>
<tr>
<th>Product</th>
<th>Unit price</th>
<th>Quantity</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<tr v-for="(cartItem, index) in order.cartItems">
<td>{{ cartItem.productName }}</td>
<td>{{ cartItem.unitPrice }}</td>
<td>{{ cartItem.quantity }}</td>
<td>{{ lineTotal[index] }}</td>
</tr>
<tr class="shipping">
<td>Shipping</td>
<td>{{ shipping }}</td>
<td>{{ totalItems }}</td>
<td></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="3">TOTAL</td>
<td></td>
</tr>
</tfoot>
</table>
</div>
这是JS:
const shipping = 1.5;
const app = new Vue({
el: '#app',
data: {
shipping: shipping.toFixed(2),
order: []
},
created() {
fetch('https://api.myjson.com/bins/1fk6ua')
.then(response => response.json())
.then(json => {
this.order = json.order
})
},
computed: {
lineTotal: function () {
return this.order.cartItems.map(function (cartItem) {
return (cartItem.unitPrice * cartItem.quantity).toFixed(2);
});
},
totalItems: function(){
return this.order.cartItems.reduce(function (totalItems, cartItem) {
return totalItems + parseInt(cartItem.quantity);
}, 0);
}
}
});
这是一个小提琴:https://jsfiddle.net/8fg70ud2/。
正如您所看到的,我只是实施的一部分。通过实施名为computed
的{{1}}功能,我获得了产品系列总数。现在,我试图通过首先获得购物车中的产品数量(最终将乘以lineTotal
常数)来获得运输线。我已经实现了shipping
功能似乎可以完成这项工作,但我注意到现在有一个控制台错误:
totalItems
深入挖掘,似乎TypeError: Cannot read property 'reduce' of undefined
函数被调用了两次;第一次totalItems
为this.order.cartItems
因此undefined
来电错误。
为什么会这样?我可能会以错误的方式处理所有这些问题,因此我愿意接受如何向前推进的建议;我在学习曲线的最开始处:)
感谢。
答案 0 :(得分:5)
创建Vue实例后,它会将属性order
初始化为[]
。在您的v-for
中,您尝试获取order.cartItems
,这也会导致undefined
,但您没有注意到任何问题,因为Vue因在v-if
内创建结构而失败了点击你的另一个计算属性lineTotal
。
但是,totalItems
会立即计算出来。 order
仍为[]
。 order.cartItems
是undefined
。这显然没有reduce
方法。因此,错误。
然后,在created
回调中,您实际获取数据并使用实际对象填充order
属性。由于order
属性是计算属性totalItems
的依赖项并且已更新,因此Vue将再次计算该属性,此次order
属性具有正确的数据结构。并且,第二次运行会很顺利。
解决方案非常简单。在包含order
元素的v-if="order.cartItems"
元素中使用tr
,等待.shipping
属性填充。