vue-组件-购物车页面案例
目录
文章目录
内容
1、 效果图展示
2、功能实现步骤
2.1、实现整体布局和样式效果
UI结构和样式不是我擅长的,这里我直接给出代码。
-
样式代码2.1-1:cart.css
/* .container { } */ .container .cart { width: 300px; /*background-color: lightgreen;*/ margin: auto; } .container .title { background-color: lightblue; height: 40px; line-height: 40px; text-align: center; /*color: #fff;*/ } .container .total { background-color: #FFCE46; height: 50px; line-height: 50px; text-align: right; } .container .total button { margin: 0 10px; background-color: #DC4C40; height: 35px; width: 80px; border: 0; } .container .total span { color: red; font-weight: bold; } .container .item { height: 55px; line-height: 55px; position: relative; border-top: 1px solid #ADD8E6; } .container .item img { width: 45px; height: 45px; margin: 5px; } .container .item .name { position: absolute; width: 90px; top: 0;left: 55px; font-size: 16px; } .container .item .change { width: 100px; position: absolute; top: 0; right: 50px; } .container .item .change a { font-size: 20px; width: 30px; text-decoration:none; background-color: lightgray; vertical-align: middle; } .container .item .change .num { width: 40px; height: 25px; } .container .item .del { position: absolute; top: 0; right: 0px; width: 40px; text-align: center; font-size: 40px; cursor: pointer; color: red; } .container .item .del:hover { background-color: orange; }
-
页面结构01_cart-tpl.html代码2.1-2:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>购物车</title> <link rel="stylesheet" href="../../assets/css/cart.css"> </head> <body> <div id="app"> <div class="container"> <div class="cart"> <div class="title">我的商品</div> <div> <div class="item"> <img src="../../assets/images/a.jpg"/> <div class="name">商品</div> <div class="change"> <a href="">-</a> <input type="text" class="num" /> <a href="">+</a> </div> <div class="del">×</div> </div> <div class="item"> <img src="../../assets/images/b.jpg"/> <div class="name">商品</div> <div class="change"> <a href="">-</a> <input type="text" class="num" /> <a href="">+</a> </div> <div class="del">×</div> </div> <div class="item"> <img src="../../assets/images/c.jpg"/> <div class="name">商品</div> <div class="change"> <a href="">-</a> <input type="text" class="num" /> <a href="">+</a> </div> <div class="del">×</div> </div> <div class="item"> <img src="../../assets/images/d.jpg"/> <div class="name">商品</div> <div class="change"> <a href="">-</a> <input type="text" class="num" /> <a href="">+</a> </div> <div class="del">×</div> </div> <div class="item"> <img src="../../assets/images/e.jpg"/> <div class="name">商品</div> <div class="change"> <a href="">-</a> <input type="text" class="num" /> <a href="">+</a> </div> <div class="del">×</div> </div> </div> <div class="total"> <span>总价:123</span> <button>结算</button> </div> </div> </div> </div> </body> </html>
2.2、运用组件化思想,划分独立的功能组件
根据结构结构功能,划分为3个独立的组件
- 头部标题组件
- 主体列表组件
- 底部结算组件
2.3、组合所有的子组件形成整体结构
组合形成的页面02_cart-component.html代码2.3-1:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>购物车</title>
<link rel="stylesheet" href="../../assets/css/cart.css">
</head>
<body>
<div id="app">
<div class="container">
<cart></cart>
</div>
</div>
<script src="../../assets/js/vue.js"></script>
<script>
Vue.component('cart-title', {
template: `
<div class="title">我的商品</div>
`
})
Vue.component('cart-list', {
template:`
<div>
<div class="item">
<img src="../../assets/images/a.jpg"/>
<div class="name">商品</div>
<div class="change">
<a href="">-</a>
<input type="text" class="num" />
<a href="">+</a>
</div>
<div class="del">×</div>
</div>
<div class="item">
<img src="../../assets/images/b.jpg"/>
<div class="name">商品</div>
<div class="change">
<a href="">-</a>
<input type="text" class="num" />
<a href="">+</a>
</div>
<div class="del">×</div>
</div>
<div class="item">
<img src="../../assets/images/c.jpg"/>
<div class="name">商品</div>
<div class="change">
<a href="">-</a>
<input type="text" class="num" />
<a href="">+</a>
</div>
<div class="del">×</div>
</div>
<div class="item">
<img src="../../assets/images/d.jpg"/>
<div class="name">商品</div>
<div class="change">
<a href="">-</a>
<input type="text" class="num" />
<a href="">+</a>
</div>
<div class="del">×</div>
</div>
<div class="item">
<img src="../../assets/images/e.jpg"/>
<div class="name">商品</div>
<div class="change">
<a href="">-</a>
<input type="text" class="num" />
<a href="">+</a>
</div>
<div class="del">×</div>
</div>
</div>
`
})
Vue.component('cart-total', {
template:`
<div class="total">
<span>总价:123</span>
<button>结算</button>
</div>
`
})
Vue.component('cart', {
template:`
<div class="cart">
<cart-title></cart-title>
<cart-list ></cart-list>
<cart-total></cart-total>
</div>
`
})
const vm = new Vue({
el: '#app'
})
</script>
</body>
</html>
2.4、逐步实现各个组件功能
2.4.1、数据如下
uname: '张三',
list: [
{
id: 1,
name: 'TCL彩电',
price: 1000,
num: 1,
img: 'images/a.jpg'
},{
id: 2,
name: '机顶盒',
price: 1000,
num: 1,
img: 'images/b.jpg'
},{
id: 3,
name: '海尔冰箱',
price: 1000,
num: 1,
img: 'images/c.jpg'
},{
id: 4,
name: '小米手机',
price: 1000,
num: 1,
img: 'img/d.jpg'
},{
id: 5,
name: 'PPTV电视',
price: 1000,
num: 2,
img: 'images/e.jpg'
}
]
2.4.2、标题组件
把标题名字‘*的商品’修改为数据中的指定名称。
-
代码2.4.2-1如下:
// cart模板修改如下 <cart-title :uname="uname"></cart-title> // cart-title组件修改如下 props: ['uname'], template: ` <div class="title">{{ uname }}的商品</div> `
-
效果图2.4.2-1:
2.4.3、列表组件
-
循环结构渲染列表
-
修改商品名称
-
初始化商品数量
// cart模板修改如下 <cart-list :list="list"></cart-list> // cart-list组件修改如下 props: ['list'], template:` <div> <div class="item" v-for="goods in list" :key="goods.id"> <img :src="'../../assets/'+goods.img"/> <div class="name">{{ goods.name }}</div> <div class="change"> <a href="">-</a> <input type="text" class="num" :value="goods.num"/> <a href="">+</a> </div> <div class="del">×</div> </div> </div> `
-
效果图2.4.3-1:
-
-
实现点击叉号删除相应列表的功能
// cart-list模板叉号绑定事件,通过$emit把对应商品ID传给父组件cart <div class="del" @click="del(goods.id)">×</div> methods: { del(id) { this.$emit('delete-goods', id) } }, // cart组件接收cart-list子组件传递的ID删除对应的商品 <cart-list :list="list" @delete-goods="deleteGoods"></cart-list> methods: { deleteGoods(id) { // console.log(id); this.list = this.list.filter(goods => { return goods.id !== id }) } },
- 效果图:
- 效果图:
-
实现编辑修改输入框数字,修改对应商品数量功能
// 修改cart-list模板添加输入框内容改变事件 <input type="text" class="num" :value="goods.num" @change="change(goods.id, $event.target.value)"/> change(id, num) { this.$emit('change-num', { id, num: parseInt(num) }) } // cart组件接收ID和改变后的数值,修改对应的商品信息 <cart-list :list="list" @delete-goods="deleteGoods" @change-num="changeNum"></cart-list> // 根据子组件cart-list修改的商品ID,数量,修改对应的商品信息 changeNum(goods) { // console.log(goods); this.list.some( item => { if(item.id === goods.id) { // console.log('前:', item.num); item.num = goods.num // console.log('后:', item.num); return true } }) }
- 效果图:
- 效果图:
-
实现点击±号按钮修改对应商品数量的功能
这里+ - 和上面的直接修改商品数量,都是在修改数量,只是修改的方式不同,这里我们添加个type标识修改方式;我们根据修改方式的不同,更改商品数量;相应的逻辑代码就可以重用。
// + - 号添加点击事件,触发父组件cart的修改数量方法
<a href="" @click.prevent="change(goods.id, 0,'sub')">-</a>
<a href="" @click.prevent="change(goods.id, 0, 'add')">+</a>
change(id, num, type) {
this.$emit('change-num', {
id,
num: parseInt(num),
type
})
}
// 父组件cart相应修改
// 根据子组件cart-list修改的商品ID,数量,修改对应的商品信息
changeNum(goods) {
// console.log(goods);
this.list.some( item => {
if(item.id === goods.id) {
// console.log('前:', item.num);
if(goods.type === 'edit') {
item.num = goods.num
} else if (goods.type === 'sub') {
item.num--
}else if (goods.type ==='add') {
item.num++
}
// console.log('后:', item.num);
return true
}
})
}
2.4.4、结算组件
// cart-total
Vue.component('cart-total', {
props: ['list'],
template:`
<div class="total">
<span>总价:{{ totalPrice }}</span>
<button>结算</button>
</div>
`,
computed: {
totalPrice() {
let total = 0
this.list.forEach(goods => {
total += goods.num * goods.price
})
return total
}
},
})
// cart组件
<cart-total :list="list"></cart-total>
3、完整代码
-
页面代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>购物车</title> <link rel="stylesheet" href="../../assets/css/cart.css"> </head> <body> <div id="app"> <div class="container"> <cart></cart> </div> </div> <script src="../../assets/js/vue.js"></script> <script> Vue.component('cart-title', { props: ['uname'], template: ` <div class="title">{{ uname }}的商品</div> ` }) Vue.component('cart-list', { props: ['list'], template:` <div> <div class="item" v-for="goods in list" :key="goods.id"> <img :src="'../../assets/'+goods.img"/> <div class="name">{{ goods.name }}</div> <div class="change"> <a href="" @click.prevent="change(goods.id, 0,'sub')">-</a> <input type="text" class="num" :value="goods.num" @change="change(goods.id, $event.target.value, 'edit')"/> <a href="" @click.prevent="change(goods.id, 0, 'add')">+</a> </div> <div class="del" @click="del(goods.id)">×</div> </div> </div> `, methods: { // 根据ID删除商品 del(id) { this.$emit('delete-goods', id) }, // 编辑商品数量,修改商品信息 change(id, num, type) { this.$emit('change-num', { id, num: parseInt(num), type }) } }, }) Vue.component('cart-total', { props: ['list'], template:` <div class="total"> <span>总价:{{ totalPrice }}</span> <button>结算</button> </div> `, computed: { totalPrice() { let total = 0 this.list.forEach(goods => { total += goods.num * goods.price }) return total } }, }) Vue.component('cart', { data() { return { uname: '张三', list: [ { id: 1, name: 'TCL彩电', price: 1000, num: 1, img: 'images/a.jpg' },{ id: 2, name: '机顶盒', price: 1000, num: 1, img: 'images/b.jpg' },{ id: 3, name: '海尔冰箱', price: 1000, num: 1, img: 'images/c.jpg' },{ id: 4, name: '小米手机', price: 1000, num: 1, img: 'images/d.jpg' },{ id: 5, name: 'PPTV电视', price: 1000, num: 2, img: 'images/e.jpg' } ]}}, template:` <div class="cart"> <cart-title :uname="uname"></cart-title> <cart-list :list="list" @delete-goods="deleteGoods" @change-num="changeNum"></cart-list> <cart-total :list="list"></cart-total> </div> `, methods: { // 根据子组件传递的ID值,删除对应的商品 deleteGoods(id) { // console.log(id); this.list = this.list.filter(goods => { return goods.id !== id }) }, // 根据子组件cart-list修改的商品ID,数量,修改对应的商品信息 changeNum(goods) { // console.log(goods); this.list.some( item => { if(item.id === goods.id) { // console.log('前:', item.num); if(goods.type === 'edit') { item.num = goods.num } else if (goods.type === 'sub') { item.num-- }else if (goods.type ==='add') { item.num++ } // console.log('后:', item.num); return true } }) } }, }) const vm = new Vue({ el: '#app' }) </script> </body> </html>
-
样式代码:同上
-
图片
-
a.jpg:
-
b.jpg:
-
c.jpg:
-
d.jpg:
-
e.jgg:
-
后记 :
vue官网地址:https://cn.vuejs.org/
本项目为参考某马视频开发,相关视频及配套资料可自行度娘或者联系本人。上面为自己编写的开发文档,持续更新。欢迎交流,本人QQ:806797785
前端项目源代码地址:https://gitee.com/gaogzhen/vue
后端JAVA源代码地址:https://gitee.com/gaogzhen/JAVA