经过一个星期左右学习Vue框架,学习完基础知识后,练习了一个购物车练习,总结一下遇到的问题。
首先看到效果图时大概想了一下,主要就是用列表和表格搭建页面。看一下整体的效果图,
效果图如上,主要实现的功能是对物品的添加,删除和物品的积分,金额,计算等。点击同一样物品时如果存在则数量累加。下面说一下遇到的问题和怎么解决的。
问题1.数据的渲染
鉴于我们是学习了Vue之后才做的练习,所以渲染数据当然是用Vue。用Vue渲染数据的话布局方面就不需要写那么多列表。只需要一个<ul><li></li></ul>标签使用v-for循环就可以了,这样省了很多代码,下面的表格也是同样的做法。代码如下:
<ul v-for="(item,index) in array[0]">
<li style="margin-right: 70px;width: 170px;"><a href="#">{{item.name}}</a></li>
<li>¥{{item.price.toFixed(2)}}</li>
<li>¥{{item.price1.toFixed(2)}}</li>
<li><a href="#" style="color: red;" @click="add1(item)">购买</a></li>
</ul>
这里我的所有数据是定义在二维数值里的,所以循环的是二维数组里的第一个数组。一开始我的数据是分开存放的,优化后就放到二维数组里。代码如下:
array:[
[
{name:"·JavaScript DOM编程艺术",price:39.00,price1:29.30,discount:75},
{name:"·解禁(当当网独家首发)",price:28.00,price1:19.40,discount:69},
{name:"·地王之王(金融危机房地产)",price:32.80,price1:25.40,discount:77},
{name:"·逃庄",price:36.00,price1:27.70,discount:76},
],
[
{name:"·MySQL数据库开发",price:59.00,price1:47.30,discount:80},
{name:"·大玩家(马未都、王刚推荐!.",price:34.80,price1:20.60,discount:59},
{name:"·都市风水师--官场风水小说",price:39.80,price1:30.50,discount:76},
{name:"·国戏(以麻将术语解读宦海沉.",price:39.00,price1:29.30,discount:75},
],
[
{name:"私募(首部披露资本博弈秘密的金融...",integral:189,price:39.00,price1:18.90,discount:48,number:1},
{name:"小团圆(张爱玲最神秘小说遗稿)",integral:173,price:28.00,price1:17.30,discount:61,number:1},
{name:"不抱怨的世界(畅销全球80国的世界...",integral:154,price:24.80,price1:15.40,discount:62,number:1},
{name:"福玛特双桶洗衣机XPB20-07S",integral:358,price:458.00,price1:358.00,discount:78,number:1},
{name:"PHP和MySQL Web开发 (原书第4版)",integral:712,price:95.00,price1:71.20,discount:74,number:1},
{name:"法布尔昆虫记",integral:130,price:198.00,price1:130.70,discount:66,number:1},
]
],
当然数据是定义在Vue的实例中的data中。
问题2.购买添加时同一物品的判断
购买添加物品呢主要就是利用数组的array.push()方法。但是遇到的问题时,当我们的物品存在时,只添加数量,而不是添加新的物品。解决的方法是在点击购买的方法中把v-for循环中的item对象当作参数传回去,方法中声明一个布尔用来判断下面是否添加,利用循环判断,先循环第三个数组,在判断传过来的item.name与第三个数组对象中的name匹配,相等则代表存在,即数量加1就好。否则在循环外添加新的物品(即一个对象)示例代码如下:
add1(item){
var num=true; //声明一个布尔变量用来做判断是否添加新的一行
for(i of this.array[2]){
if (item.name==i.name) { //如果名称一样就不添加
num=false; //并返回false
i.number++; //但是数量累加
}
}
if (num) { //循环外 再判断布尔 为true 即添加新行
this.array[2].push({name:item.name,integral:(item.price1)*10,price:item.price,price1:item.price1,discount:item.discount,number:1})
}
},
上述代码都有相应的注释。当然方法是要定义在Vue实例中的methods中。
问题3.删除根据index删除
删除的方法比较简单,利用数组的array.splice()方法。问题就是我们需要删除对应的对象,这时候可以根据数组下标来删除。再删除的方法中把index传值传回去。代码如下:
detele(index){
this.array[2].splice(index,1)//根据传过来的index删除对象的tr
},
问题4.金额积分的计算
做到这里的时候刚刚开始时蒙圈的,蒙圈的不是如何写代码,是发现自己对Vue理解的不够深,一时之间不知道该把对应的方法写在那里,又如何来触发,不像之前的jq或者js直接写个加载方法,把结果计算出来,该调用的地方就调用。后来请教了一下同学,才发现Vue里面的计算属性(computed)就是专门写这些的。简单的理解就是把方法当做属性来使用,在我们的方法中把计算的结果用返回值的方式返回出去。明白这一点之后,就透彻了。首先在HTML代码中定义我们的计算属性,代码如下:
<ul>
<li>
<p><label>您共节省</label><span>¥{{save}}</span></p>
<p><label>可获商品积分:</label><span class="integrals">{{aggregates}}</span></p>
</li>
<li><p><label>商品金额总计:</label><span>¥{{money}}</span></p></li>
<li style="cursor: pointer;"><p><img src="img/shopping_balance.gif"/><p></li>
</ul>
再之后就是写方法了。先明白我们要拿到的数据是单品积分,数量,未打折单价,打折后单价。剩下的就是简单的数学问题了。总积分=单品积分*数量 总金额=(未打折单价*数量)-(打折单价*数量)。代码如下:
//计算属性
computed:{
//总积分
aggregates(){
var nums=0; //总积分
for(item of this.array[2]){
nums+=item.integral*item.number //单品积分*数量
}
return nums
},
//总金额
money(){
var moneys=0;
for(item of this.array[2]){
moneys+=item.price1*item.number //总金额累加=数量 *价格
}
return moneys.toFixed(2)
},
//节省金额
save(){
var saves=0; //未打折的总价
var moneys=0; //打折后的总价
for(item of this.array[2]){
saves+=item.price*item.number //未打折的总金额=未打折单价*数量
moneys+=item.price1*item.number //打折总金额累加=打折价格*数量
}
return (saves-moneys).toFixed(2)
}
}
这样就完成了我们的计算。当然这些方法都要定义在Vue实例中的computed中。
问题5.用户输入数量,负数和小数
上述我们已经实现了,添加,删除,积分金额的计算。后面我发现一个bug,就是如果我们的用户输入的数量是负数和小数的话,它一样的计算,这样不符合我们的逻辑,物品没有小数,金额不可能为负数。解决的方法是在我们的输入框中利用v-on:blur绑定了一个失去焦点事件,当我们失去焦点时在方法中利用正则表达式匹配,只能为正数,为负数或者有小数时我们弹出框提示客户不能为负数和小数,强制把数量赋值为初始值1。代码如下:
//数量输入框离开事件
blurs(item){
var reg=/^[1-9][0-9]{0,}$/ //正则表达式 1-9开头后续0-9任意数
if(!reg.test(item.number)){ //如果不满足
alert("亲( • ̀ω•́ )✧ 购买数量不能为负数或小数!")
item.number=1 ; //就赋值为1 避免用户输入负数
}
}
通过这次的练习认识到自己的不足,对Vue理解的不够深,对之前的知识点不够扎实,如数据的转换,字符串转数字类型。一些数组的方法。另外还有一些其他问题,例如我们的数量是用数组对象渲染到双向绑定(v-model="item.number")上的,不知道该如何监听。for-in循环和for-of循环的区别。什么时候用for-in循环,什么时候用for-of循环。什么又是深度监听?温故而知新,建议要多多回顾之前的知识。欢迎在下面评论区帮忙解答此处@曹老师,谢谢大家。