vuejs⼿把⼿教你写⼀个完整的购物车实例代码
由于我们公司是主营业务是海淘,所以每个项⽬都是类似淘宝天猫之类的商城,那么购物车就是⼀个重点开发功能模块。介于之前我都是⽤jq来写购物车的,这次就⽤vuejs来写⼀个购物车。下⾯我就从全选,数量控制器,运费,商品⾦额计算等⽅法来演⽰⼀下⼀个能⽤在实际场景的购物车是怎么做出来的以及记录⼀下这次⽤vuejs踩过的坑。
1.⼀层数据结构-全选
下⾯这段代码和vuejs官⽹⾥⾯checkbox绑定很像。不明⽩的可以直接上vuejs官⽹看看。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuejs-全选</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
a {
color: #333;
text-decoration:none;
}
</style>
</head>
<body>
<label>
<input type="checkbox" name="all" v-on:click="chooseAll" v-model="selectArr.length==goodsList.length" />
<span>全选</span>
</label>
<div v-for="(index, item) in goodsList">
<a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >
<input type="checkbox" :value="index" v-model="selectArr" />
商品名称:<span v-html="item.name"></span> |
价格:<span v-html="item.price"></span>
</a>
</div>
<label>
<input type="checkbox" name="all" v-on:click="chooseAll" v-model="selectArr.length==goodsList.length" />
<span>全选</span>
</label>
<script src="cdn.bootcss/vue/1.0.7/vue.js"></script>
<script>
var vue = new Vue({
el : 'body',
data : {
goodsList : [
{
name : '⼭本汉⽅1',
price : '19.00'
},
{
name : '⼭本汉⽅2',
price : '19.00'
},
{
name : '⼭本汉⽅3',
price : '19.00'
},
{
name : '⼭本汉⽅4',
price : '19.00'
},
{
name : '⼭本汉⽅5',
price : '19.00'
},
],
selectArr : []
},
ready : function() {},
methods : {
chooseAll : function(event) {
var oThis = this;
oThis.selectArr = [];
if ( event.currentTarget.checked ) {
oThis.selectArr.push(index);
});
}网页购物车代码
console.log(oThis.selectArr);
}
}
})
</script>
</body>
</html>
2.⼆层数据结构-全选
⼀层数据结构的购物车在现实中是很少看到的,⽐如我们最熟悉的淘宝购物车是按照店铺分的,那么必然是多层的数据结构。这次在写这个⼆层数据接⼝的全选,碰到⼀个很⼤的坑,⼀开始我是⽤了⼀层数据结构的数据,发现当对象数组⾥⾯的某个值改变了,视图竟然没有触发!,所以会造成下⾯所
有的checkbox都被选中了,最上⾯的那个全选checkbox 竟然还是没有被选中。感觉告诉我这是vuejs的坑,后来发现是js的坑。具体可以看这个。⽅法是百度到了,可是放我这⾥没有⽤(应该是版本问题)。于是我就改了数据结构。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuejs-全选</title>
<style type="text/css">
* {
padding: 0;
margin: 0;
}
a {
color: #333;
text-decoration:none;
}
.goods-item {
display: block;
}
.store-item {
margin-bottom: 20px;
}
</style>
</head>
<body>
<div v-for="(index1, item) in goodsObj" class="store-item">
<p>
<span v-html="item.name"></span>
<label>
<input type="checkbox" name="all" v-on:click="chooseShopGoods(index1)" v-model="item.checked" />
<span>全选</span>
</label>
</p>
<a href="javascript:;" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" v-for="(index, data) in item.list" class="goods-item">    <input type="checkbox" v-model="data.checked" v-on:click="choose(index1, index)" />
商品名称:<span v-html="data.name"></span> |
价格:<span v-html="data.price"></span>
</a>
</div>
<label>
<input type="checkbox" name="all" v-on:click="chooseAllGoods()" v-model="allChecked" />
<span>全选</span>
</label>
<script src="cdn.bootcss/vue/1.0.7/vue.js"></script>
<script>
var goodsObj = [
{
name : '⼤胖的店',
checked : false,
list : [
{
name : '⿇辣⼆胖',
price : 23.00,
realStock : 10,
fare : 1.5,
num : 1,
checked : false,
},
{
name : '⾹辣⼆胖',
price : 21.00,
realStock : 2,
fare : 1.5,
num : 2,
checked : false,
},
{
name : '红烧⼆胖',
price : 88.00,
realStock : 8,
fare : 1.5,
num : 4,
checked : false,
}
]
},
{
name : '⼆胖的店',
checked : false,
list : [
{
name : '漂亮的裙⼦',
price : 166.00,
realStock : 10,
fare : 2,
num : 1,
checked : false,
},
{
name : '漂亮的短袖',
price : 188.00,
realStock : 2,
fare : 1.5,
num : 2,
checked : false,
},
{
name : '漂亮的鞋⼦',
price : 299.00,
realStock : 1,
fare : 3,
num : 1,
checked : false,
}
]
},
{
name : '胖胖的店',
checked : false,
list : [
{
name : '福满多',
price : 3.00,
realStock : 10,
fare : .5,
num : 10,
checked : false,
{
name : '精品卫龙',
price : 1.50,
realStock : 2,
fare : 2,
num : 2,
checked : false,
},
{
name : '周长江',
price : 2.50,
realStock : 3,
fare : 5,
num : 2,
checked : false,
}
]
},
];
var vue = new Vue({
el : 'body',
data : {
goodsObj : goodsObj,
allChecked : false
},
ready : function() {
},
methods : {
// 全部商品全选
chooseAllGoods : function() {
var flag = true;
if ( this.allChecked ) {
flag = false;
}
for ( var i = 0, len = dsObj.length; i < len; i++ ) {
var list = dsObj[i]['list'];
for ( var k = 0, len1 = list.length; k < len1; k++ ) {
list[k]['checked'] = flag;
}
}
this.allChecked = !this.allChecked;
},
// 每个店铺全选
chooseShopGoods : function( index) {
var list = dsObj[index]['list'],
len = list.length;
if ( dsObj[index]['checked'] ) {
for (var i = 0; i < len; i++ ) {
list[i]['checked'] = false;
}
} else {
for (var i = 0; i < len; i++ ) {
list[i]['checked'] = true;
}
}
// 判断是否选择所有商品的全选
this.isChooseAll();
},
// 单个选择
choose : function( index1, index) {
var list = dsObj[index1]['list'],
len = list.length;
if ( list[index]['checked'] ) {
this.allChecked = false;
list[index]['checked'] = !list[index]['checked'];
} else {
list[index]['checked'] = !list[index]['checked'];
/
/ 判断是否选择当前店铺的全选
var flag = true;
for (var i = 0; i < len; i++ ) {
if ( list[i]['checked'] == false ) {
flag = false;
break;
}
}
flag == true ? dsObj[index1]['checked'] = true : dsObj[index1]['checked'] = false;      }
// 判断是否选择所有商品的全选
this.isChooseAll();
},
// 判断是否选择所有商品的全选
isChooseAll : function() {
var flag1 = true;
for ( var i = 0, len = dsObj.length; i < len; i++ ) {
if ( dsObj[i]['checked'] == false ) {
flag1 = false;
break;
}
}
flag1 == true ? this.allChecked = true : this.allChecked = false;
},
}
})
</script>
</body>
3.⼀层数据结构-数量选择器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuejs-数量选择器(1层数据结构)</title>
<style type="text/css">
*{
padding:0;
margin: 0;
box-sizing: border-box;
font-size: 16px;
}
.clearfix:after {
content: ".";
visibility: hidden;
display: block;
height: .1px;
font-size: .1em;
line-height: 0;
clear: both;
}
.quantity-selector {
margin-bottom: 20px;
width: 8.571rem;
line-height: 2.857rem;
border: 1px solid #d1d6e4;
border-radius: 3px;
}
.quantity-selector .reduce,
.quantity-selector .add {
float: left;
width: 33.33%;
border-right: 1px solid #d1d6e4;
text-align: center;
cursor: pointer;
}
.quantity-selector .number {
float: left;
width: 33.33%;
height: 2.857rem;
padding: .5rem 0;
line-height: 1rem;
border: none;
text-align: center;
}
.quantity-selector .add {
border-left: 1px solid #d1d6e4;
border-right: none;
}
.
quantity-selector .disable {
color: #d2d2d2;
cursor: default;
}
</style>
</head>
<body>
<div v-for="data in goodsList">
<p>商品数量:<span v-html="data.num"></span></p>
<p>商品库存:<span v-html="alStock"></span></p>
<div class="quantity-selector clearfix">
<span class="reduce" v-on:click="numChange($index, -1)" v-bind:class="{ 'disable' : data.num==1 }">-</span>
<input type="number" v-bind:value="data.num" class="number" v-bind:data-realStock="alStock" v-on:keyUp="numEntry($index)" v-on:keyDown="numEntry($index)" v-model="data.num"/>    <span class="add" v-on:click="numChange($index, 1)" v-bind:class="{ 'disable' : data.num==alStock }">+</span>
</div>
</div>
<script src="cdn.bootcss/vue/1.0.7/vue.js"></script>
<script>
var vue = new Vue({
el : 'body',
data : {
goodsList : [
{
name : '⼭本汉⽅1',
price : '19.00',
realStock : 10,
num : 1
},
{
name : '⼭本汉⽅1',
price : '19.00',
realStock : 7,
num : 8
},
{
name : '⼭本汉⽅1',
price : '19.00',
realStock : 2,
num : 2
},
]
},
ready : function() {},
methods : {
numChange : function(index, numChange) {
var goods = dsList[index];
if ( numChange == 1 ) {
goods.num++;
} else if ( numChange == -1 ) {
goods.num--;
}
if ( goods.num <= 1 ) {
goods.num = 1;
}
if ( goods.num >= alStock ) {        goods.num = alStock;
}
},
numEntry : function(index) {
var goods = dsList[index];
if ( goods.num <=1 ) {
goods.num = 1;
}
if ( goods.num > alStock ) {
goods.num = alStock;
}
}
}
})
</script>
</body>
</html>
4.⼆层数据结构-数据选择器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vuejs-数量选择器(2层数据结构)</title> <style type="text/css">
*{
padding:0;
margin: 0;
box-sizing: border-box;
font-size: 16px;
}
a {
text-decoration: none;
color: #333;
}
.
clearfix:after {
content: ".";
visibility: hidden;
display: block;
height: .1px;
font-size: .1em;
line-height: 0;
clear: both;
}
.quantity-selector {
margin: 0 auto;
width: 8.571rem;
line-height: 30px;
border: 1px solid #d1d6e4;
border-radius: 3px;
}
.quantity-selector .reduce,
.quantity-selector .add {
float: left;
width: 33.33%;
border-right: 1px solid #d1d6e4;
text-align: center;
cursor: pointer;
}
.quantity-selector .number {
float: left;
width: 33.33%;
height: 30px;
border: none;
padding-left: 10px;
text-align: center;
}
.quantity-selector .add {
border-left: 1px solid #d1d6e4;
border-right: none;
}
.quantity-selector .disable {
color: #d2d2d2;
cursor: default;
}
/*店铺开始*/
.store-item {
width: 600px;
margin: 30px auto;
}
.store-item th {
height: 40px;
background: #d2d2d2;
-webkit-text-stroke: 1px #ff7500;
font-size: 18px;
}
.store-item td {
height: 60px;
text-align: center;
}
.
cal-store-box {
text-align: right;
}
.store-footer {
width: 600px;
margin: 50px auto;
display: flex;
justify-content: space-between;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。