Vue实现购物车功能
使用Vue组件完成一个带自动计算、删除、修改、选择、搜索、添加功能的购物车功能
·
使用Vue组件完成一个带自动计算、删除、修改、选择、搜索、添加功能的购物车功能
效果预览:
步骤:
1.创建子组件:
里面存放的是我们需要传输给购物车的内容,运用父子组件传值(props,$emit)完成传输。
<template id="goods">
<div class="goods-content" :style="{backgroundColor:(index%2==0?'':'#E2DFDF')}">
<div class="goods-select">
<input type="checkbox" v-model="goods.select">
</div>
<div class="goods-id">
<img :src="goods.imgSrc">
</div>
<div class="goods-name">
{{goods.name}}
</div>
<div class="goods-price">
{{goods.price}}
</div>
<div class="goods-number">
<button @click="reduce(index)" style="background-color: #ebcaca;border: #eebbbb;">-</button>
<input type="text" v-model="goods.number" style="border: none" />
<button @click="add(index)" style="background-color: #ebcaca;border: #eebbbb;">+</button>
</div>
<div class="goods-opt">
<button @click="del(index)" style="background-color: #ebcaca;border: #eebbbb;">删除</button>
</div>
</div>
</template>
<script type="text/javascript">
Vue.component( "goods", {
template: "#goods",
props: [ "goods", "index" ],
methods: {
add ( index )
{
this.goods.number++;
this.$emit( "toupdate", index, this.goods.number );
},
reduce ( index )
{
if ( this.goods.number > 0 )
{
this.goods.number--;
this.$emit( "toupdate", index, this.goods.number );
} else
{
alert( "数量不能再少了" );
}
},
del ( index )
{
this.$emit( 'todel', index );
}
}
} );
</script>
2.页面布局:
简单实现页面效果。
<div id="app">
<div class="find">
<input type="text" placeholder="请输入您要查询的物品" id="n" v-model="find">
</div>
<div class="form-content">
<div id="BOX">
<div id="boxs" v-for="(i,id) in finishs" :key="i.id">
<img :src="i.imgSrc">
<p> 商品名称:{{i.name}}</p>
<p> 商品价格:{{i.price}}元</p>
<button type="button" @click="insert(i)">添加至购物车</button>
</div>
</div>
</div>
<div class="content">
<h3>购物车</h3>
<div class="goods-content" style="background-color: #ebcaca;">
<div class="goods-select">
选择
</div>
<div class="goods-id">
编号
</div>
<div class="goods-name">
商品名称
</div>
<div class="goods-price">
单价
</div>
<div class="goods-number">
数量
</div>
<div class="goods-opt">
操作
</div>
</div>
<goods v-for="(goods,index) in goodsList" :key="goods.id" :goods="goods" :index="index" @todel="del"
@toupdate="update">
</goods>
<div id="bl">您的购物车内暂无商品,快去选购吧</div>
<div id="AllSelect">
<input type="checkbox" v-model="allCheck" />全选
</div>
<div class="total">总价:¥{{total}}元</div>
</div>
</div>
3.样式文件:
(此处与页面布局依照自己喜好即可)。
body {
font-size: 18px;
}
.find {
width: 604px;
height: 90px;
margin: 0 auto;
}
.find input {
margin-top: 10px;
width: 600px;
height: 40px;
border: 2px solid #eebbbb;
border-radius: 25px;
}
#BOX {
width: 1200px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
font-size: 12px;
}
#boxs {
width: 185px;
border: 1px solid #eac2c2;
border-radius: 6px;
}
#boxs p {
padding-left: 10px;
}
#boxs img {
width: 167px;
height: 150px;
margin: 4% 5%;
border-radius: 7px;
}
#boxs button {
margin: 0 18% 4%;
background-color: #eac2c2;
border: none;
height: 35px;
width: 120px;
border-radius: 5px;
font-family: '宋体';
color: aliceblue;
}
.form-content {
width: 1200px;
margin: 0 auto;
}
.content {
width: 1200px;
margin: 0 auto;
margin-bottom: 70px;
}
.goods-content {
line-height: 60px;
width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
}
.goods-content div {
display: inline-block;
margin-bottom: 1px;
font-size: 15px;
}
.goods-select {
width: 3%;
text-align: center;
}
.goods-id {
width: 20%;
text-align: center;
}
.goods-id img {
width: 100px;
margin-top: 18px;
}
.goods-name {
width: 37%;
}
.goods-price {
width: 10%;
text-align: center;
}
.goods-number {
width: 20%;
text-align: center;
}
.goods-opt {
width: 10%;
text-align: center;
}
.goods-opt button {
width: 60px;
height: 30px;
}
.goods-content input {
height: 20px;
width: 16px;
}
.total {
background: #eac2c2;
width: 1200px;
text-align: right;
margin: 0 auto;
margin-top: 30px;
position: fixed;
bottom: 0;
}
#bl {
width: 1200px;
margin: 0 auto;
text-align: center;
font-size: 30px;
font-family: '宋体';
color: #ccc;
}
#AllSelect {
background: #eac2c2;
width: 1200px;
margin: 0 auto;
height: 50px;
position: fixed;
bottom: 20px;
}
4.实现购物车中无商品时显示“您的购物车内暂无商品,快去选购吧”,有商品时文字消失功能:
使用监听属性对购物车数组进行监听,当数组长度为0时,display设置为block,也就是显示样式,当数组长度不为0时,display设置为none,不显示样式。
watch: {
goodsList ()
{
if ( this.goodsList.length !== 0 )
{
document.getElementById( 'bl' ).style.display = 'none';
} else
{
document.getElementById( 'bl' ).style.display = 'block';
}
}
}
5.实现加入购物车功能:
使用push()进行对数组元素的添加。
insert ( i )
{
if ( this.goodsList == '' )
{
this.goodsList.push( i )
} else
{
if ( this.goodsList.includes( i ) )
{
var index = this.goodsList.indexOf( i )
this.goodsList[ index ].number++
} else
{
this.goodsList.push( i )
}
}
}
5.实现删除购物车内容功能:
使用splice()进行对数组元素的删除。
del ( index )
{
this.goodsList.splice( index, 1 );
}
6.实现全选按钮功能:
用every()(用于遍历数组中所有元素,只要有一项不符合要求,便返回false,全符合要求则返回true)实现其他按钮全部被选中时,全选按钮也被选中,用forEach()(用于调用数组的每个元素,并将元素传递给回调函数)实现点击全选按钮其他按钮全部被选中效果。
computed: {
allCheck: {
get ()
{
if ( this.goodsList.length == 0 )
{
select = false;
} else
{
return this.goodsList.every( i => i.select )
}
},
set ( val )
{
this.goodsList.forEach( Element =>
{
Element.select = val;
} );
}
}
}
7.实现合计计算功能:
对数组进行遍历,如果是选中状态则用数量乘上价格进行相加,未被选中的不参与计算。
computed: {
total ()
{
var money = 0;
for ( var i = 0; i < this.goodsList.length; i++ )
{
if ( this.goodsList[ i ].select == true )
{
money += ( parseFloat( this.goodsList[ i ].price ) *
parseFloat( this.goodsList[ i ].number ) );
}
}
return money;
}
}
8.实现搜索框功能:
使用filter()方法过滤数组中元素,indexOf()方法返回指定字符串。
computed: {
finishs ()
{
return this.BoxImg.filter( ( item ) =>
{
return item.name.indexOf( this.find ) !== -1
} )
}
}
完整代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="js/vue.js"></script>
<style>
body {
font-size: 18px;
}
.find {
width: 604px;
height: 90px;
margin: 0 auto;
}
.find input {
margin-top: 10px;
width: 600px;
height: 40px;
border: 2px solid #eebbbb;
border-radius: 25px;
}
#BOX {
width: 1200px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
font-size: 12px;
}
#boxs {
width: 185px;
border: 1px solid #eac2c2;
border-radius: 6px;
}
#boxs p {
padding-left: 10px;
}
#boxs img {
width: 167px;
height: 150px;
margin: 4% 5%;
border-radius: 7px;
}
#boxs button {
margin: 0 18% 4%;
background-color: #eac2c2;
border: none;
height: 35px;
width: 120px;
border-radius: 5px;
font-family: '宋体';
color: aliceblue;
}
.form-content {
width: 1200px;
margin: 0 auto;
}
.content {
width: 1200px;
margin: 0 auto;
margin-bottom: 70px;
}
.goods-content {
line-height: 60px;
width: 1200px;
margin: 0 auto;
display: flex;
justify-content: space-between;
}
.goods-content div {
display: inline-block;
margin-bottom: 1px;
font-size: 15px;
}
.goods-select {
width: 3%;
text-align: center;
}
.goods-id {
width: 20%;
text-align: center;
}
.goods-id img {
width: 100px;
margin-top: 18px;
}
.goods-name {
width: 37%;
}
.goods-price {
width: 10%;
text-align: center;
}
.goods-number {
width: 20%;
text-align: center;
}
.goods-opt {
width: 10%;
text-align: center;
}
.goods-opt button {
width: 60px;
height: 30px;
}
.goods-content input {
height: 20px;
width: 16px;
}
.total {
background: #eac2c2;
width: 1200px;
text-align: right;
margin: 0 auto;
margin-top: 30px;
position: fixed;
bottom: 0;
}
#bl {
width: 1200px;
margin: 0 auto;
text-align: center;
font-size: 30px;
font-family: '宋体';
color: #ccc;
}
#AllSelect {
background: #eac2c2;
width: 1200px;
margin: 0 auto;
height: 50px;
position: fixed;
bottom: 20px;
}
</style>
</head>
<body>
<div id="app">
<div class="find">
<input type="text" placeholder="请输入您要查询的物品" id="n" v-model="find">
</div>
<div class="form-content">
<div id="BOX">
<div id="boxs" v-for="(i,id) in finishs" :key="i.id">
<img :src="i.imgSrc">
<p> 商品名称:{{i.name}}</p>
<p> 商品价格:{{i.price}}元</p>
<button type="button" @click="insert(i)">添加至购物车</button>
</div>
</div>
</div>
<div class="content">
<h3>购物车</h3>
<div class="goods-content" style="background-color: #ebcaca;">
<div class="goods-select">
选择
</div>
<div class="goods-id">
编号
</div>
<div class="goods-name">
商品名称
</div>
<div class="goods-price">
单价
</div>
<div class="goods-number">
数量
</div>
<div class="goods-opt">
操作
</div>
</div>
<goods v-for="(goods,index) in goodsList" :key="goods.id" :goods="goods" :index="index" @todel="del"
@toupdate="update">
</goods>
<div id="bl">您的购物车内暂无商品,快去选购吧</div>
<div id="AllSelect">
<input type="checkbox" v-model="allCheck" />全选
</div>
<div class="total">总价:¥{{total}}元</div>
</div>
</div>
</body>
<template id="goods">
<div class="goods-content" :style="{backgroundColor:(index%2==0?'':'#E2DFDF')}">
<div class="goods-select">
<input type="checkbox" v-model="goods.select">
</div>
<div class="goods-id">
<img :src="goods.imgSrc">
</div>
<div class="goods-name">
{{goods.name}}
</div>
<div class="goods-price">
{{goods.price}}
</div>
<div class="goods-number">
<button @click="reduce(index)" style="background-color: #ebcaca;border: #eebbbb;">-</button>
<input type="text" v-model="goods.number" style="border: none" />
<button @click="add(index)" style="background-color: #ebcaca;border: #eebbbb;">+</button>
</div>
<div class="goods-opt">
<button @click="del(index)" style="background-color: #ebcaca;border: #eebbbb;">删除</button>
</div>
</div>
</template>
<script type="text/javascript">
Vue.component( "goods", {
template: "#goods",
props: [ "goods", "index" ],
methods: {
add ( index )
{
this.goods.number++;
this.$emit( "toupdate", index, this.goods.number );
},
reduce ( index )
{
if ( this.goods.number > 0 )
{
this.goods.number--;
this.$emit( "toupdate", index, this.goods.number );
} else
{
alert( "数量不能再少了" );
}
},
del ( index )
{
this.$emit( 'todel', index );
}
}
} );
var vm = new Vue( {
el: "#app",
data: {
goodsList: [],
BoxImg: [
{ select: true, id: 1, imgSrc: 'img/1.jpg', price: '8', name: '小毛球袜子黑色', number: '1' },
{ select: true, id: 2, imgSrc: 'img/2.jpg', price: '8', name: '小毛球袜子紫色', number: '1' },
{ select: true, id: 3, imgSrc: 'img/3.jpg', price: '8', name: '小毛球袜子玫红色', number: '1' },
{ select: true, id: 4, imgSrc: 'img/4.jpg', price: '8', name: '小毛球袜子绿色', number: '1' },
{ select: true, id: 5, imgSrc: 'img/5.jpg', price: '8', name: '小毛球袜子淡粉色', number: '1' },
{ select: true, id: 6, imgSrc: 'img/6.jpg', price: '8', name: '小毛球白袜子粉球', number: '1' },
{ select: true, id: 7, imgSrc: 'img/7.jpg', price: '8', name: '小毛球袜子黄色', number: '1' },
{ select: true, id: 8, imgSrc: 'img/8.jpg', price: '8', name: '小毛球袜子白色', number: '1' },
{ select: true, id: 9, imgSrc: 'img/9.jpg', price: '6', name: '小白熊袜子黑色', number: '1' },
{ select: true, id: 10, imgSrc: 'img/10.jpg', price: '7', name: '小翅膀袜子灰色', number: '1' },
{ select: true, id: 11, imgSrc: 'img/11.jpg', price: '5', name: '小兔子袜子黄色', number: '1' },
{ select: true, id: 12, imgSrc: 'img/12.jpg', price: '3', name: '小怪物袜子粉色', number: '1' },
{ select: true, id: 13, imgSrc: 'img/13.jpg', price: '3', name: '小怪物袜子白色', number: '1' },
{ select: true, id: 14, imgSrc: 'img/14.jpg', price: '3', name: '小怪物袜子绿色', number: '1' },
{ select: true, id: 15, imgSrc: 'img/15.jpg', price: '3', name: '小怪物袜子卡其色', number: '1' },
{ select: true, id: 16, imgSrc: 'img/16.jpg', price: '9', name: '小熊猫袜子黑白两色', number: '1' },
{ select: true, id: 17, imgSrc: 'img/17.jpg', price: '12', name: '大眼睛袜子黑白两色', number: '1' },
{ select: true, id: 18, imgSrc: 'img/18.jpg', price: '12', name: '大眼睛条纹袜子两色', number: '1' },
],
find: ''
},
methods: {
insert ( i )
{
if ( this.goodsList == '' )
{
this.goodsList.push( i )
} else
{
if ( this.goodsList.includes( i ) )
{
var index = this.goodsList.indexOf( i )
this.goodsList[ index ].number++
} else
{
this.goodsList.push( i )
}
}
},
update ( index, number )
{
this.goodsList[ index ].number = number;
},
del ( index )
{
this.goodsList.splice( index, 1 );
},
},
computed: {
allCheck: {
get ()
{
if ( this.goodsList.length == 0 )
{
select = false;
} else
{
return this.goodsList.every( i => i.select )
}
},
set ( val )
{
this.goodsList.forEach( Element =>
{
Element.select = val;
} );
}
},
total ()
{
var money = 0;
for ( var i = 0; i < this.goodsList.length; i++ )
{
if ( this.goodsList[ i ].select == true )
{
money += ( parseFloat( this.goodsList[ i ].price ) *
parseFloat( this.goodsList[ i ].number ) );
}
}
return money;
},
finishs ()
{
return this.BoxImg.filter( ( item ) =>
{
return item.name.indexOf( this.find ) !== -1
} )
}
},
watch: {
goodsList ()
{
if ( this.goodsList.length !== 0 )
{
document.getElementById( 'bl' ).style.display = 'none';
} else
{
document.getElementById( 'bl' ).style.display = 'block';
}
}
},
} )
</script>
</html>
更多推荐
已为社区贡献2条内容
所有评论(0)