<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.5/vue.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
input {
outline: none;
width: 30px;
height: 30px;
margin: 0 5px;
}
button {
width: 20px;
font-size: 20px;
}
#cart {
width: 500px;
margin: 50px auto;
}
.title {
background-color: #A2C8D5;
text-align: center;
height: 50px;
line-height: 50px;
}
li {
font-size: 20px;
height: 70px;
line-height: 70px;
background-color: #E9E9E9;
padding: 0 10px;
border-bottom: 2px solid #C5CDCB;
}
li span:first-of-type {
float: left;
}
li span:last-of-type {
float: right;
margin-left: 20px;
color: #D61615;
font-size: 60px;
cursor: pointer;
width: 70px;
text-align: center;
}
li span:last-of-type:hover {
background-color: #f7b709;
}
li .btn {
float: right;
}
.footer {
height: 70px;
background-color: #E8C04A;
line-height: 70px;
text-align: center;
position: relative;
}
.footer>span:first-child {
color: red;
font-size: 25px;
}
.footer>span:last-child {
position: absolute;
top: 50%;
right: 40px;
transform: translateY(-50%);
width: 80px;
height: 40px;
background-color: #CC4F45;
line-height: 40px;
}
</style>
</head>
<body>
<div id="app">
<my-cart></my-cart>
</div>
<script>
// 购物车标题子组件
let cartTitle = {
props: ['uname'],
template: ` <div class="title">{{uname}}的商品</div>`
}
// 购物车商品列表子组件
let cartList = {
props: ['list'],
template: `<ul>
<li :key="item.id" v-for="(item,index) in list"><span>{{item.name+' 价格: '+item.price}}</span><span @click="del(index)">×</span>
<div class="btn"><button @click="sub(index)">-</button><input type="text" :value="item.num" @blur="changeNum(index,$event)"><button @click="add(index)">+</button></div>
</li>
</ul>`,
methods: {
del(i) {
this.$emit('cart-del', i);
},
changeNum(i, e) {
this.$emit('goods-num', {
id: i,
num: e.target.value,
type: 'inputChange'
})
},
sub(i) {
this.$emit('goods-num', {
id: i,
type: 'subChange'
})
},
add(i) {
this.$emit('goods-num', {
id: i,
type: 'addChange'
})
}
}
}
// 购物车总价子组件
let cartTotal = {
props: ['list'],
template: ` <div class="footer">
<span>总价:<span>{{sum}}</span></span>
<span>结算</span>
</div>`,
computed: {
sum() {
let sum = this.list.reduce((total, e) => {
return total + e.price * e.num;
}, 0)
return sum;
}
}
}
// 购物车父组件
Vue.component('my-cart', {
data: function() {
return {
uname: '张三',
list: [{
id: 1,
name: '手机',
price: 6000,
num: 1
}, {
id: 2,
name: '电脑',
price: 8000,
num: 1
}, {
id: 3,
name: '耳机',
price: 200,
num: 5
}, {
id: 4,
name: '充电宝',
price: 100,
num: 10
}]
}
},
template: `<div id="cart">
<cart-title :uname="uname"></cart-title>
<cart-list :list="list" @cart-del="del($event)" @goods-num="changeNum($event)"></cart-list>
<cart-total :list="list"></cart-total>
</div>`,
components: {
'cart-title': cartTitle,
'cart-list': cartList,
'cart-total': cartTotal
},
methods: {
del(i) {
this.list.splice(i, 1);
},
changeNum(e) {
if (e.type == 'inputChange') {
this.list[e.id].num = e.num;
} else if (e.type == 'addChange') {
this.list[e.id].num++;
} else {
if (this.list[e.id].num == 0) {
this.list[e.id].num = 0;
} else {
this.list[e.id].num--;
}
}
}
}
})
let vu = new Vue({
el: '#app',
data: {}
})
</script>
</body>
</html>
https://juejin.cn/post/7148754381645545502
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.5/vue.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
input {
outline: none;
width: 30px;
height: 30px;
margin: 0 5px;
}
button {
width: 20px;
font-size: 20px;
}
#cart {
width: 500px;
margin: 50px auto;
}
li {
font-size: 20px;
height: 70px;
line-height: 70px;
background-color: #E9E9E9;
padding: 0 10px;
border-bottom: 2px solid #C5CDCB;
}
li span:first-of-type {
float: left;
}
li span:last-of-type {
float: right;
margin-left: 20px;
color: #D61615;
font-size: 60px;
cursor: pointer;
width: 70px;
text-align: center;
}
li span:last-of-type:hover {
background-color: #f7b709;
}
li .btn {
float: right;
}
.footer {
height: 70px;
background-color: #E8C04A;
line-height: 70px;
text-align: center;
position: relative;
}
.footer>span:first-child {
color: red;
font-size: 25px;
}
.footer>span:last-child {
position: absolute;
top: 50%;
right: 40px;
transform: translateY(-50%);
width: 80px;
height: 40px;
background-color: #CC4F45;
line-height: 40px;
}
</style>
</head>
<body>
<div id="app">
<my-cart></my-cart>
</div>
<script>
// 购物车商品列表子组件
let cartList = {
props: ['list'],
template: `<ul>
<li :key="item.id" v-for="(item,index) in list"><span>{{item.name+' 价格: '+item.price}}</span><span @click="del(index)">×</span>
<div class="btn"><button @click="sub(index)">-</button><input type="text" :value="item.num" @blur="changeNum(index,$event)"><button @click="add(index)">+</button></div>
</li>
</ul>`,
methods: {
del(i) {
this.$emit('cart-del', i);
},
changeNum(i, e) {
this.$emit('goods-num', {
id: i,
num: e.target.value,
type: 'inputChange'
})
},
sub(i) {
this.$emit('goods-num', {
id: i,
type: 'subChange'
})
},
add(i) {
this.$emit('goods-num', {
id: i,
type: 'addChange'
})
}
}
}
// 购物车总价子组件
let cartTotal = {
props: ['list'],
template: ` <div class="footer">
<span>总价:<span>{{sum}}</span></span>
<span>结算</span>
</div>`,
computed: {
sum() {
let sum = this.list.reduce((total, e) => {
return total + e.price * e.num;
}, 0)
return sum;
}
}
}
// 购物车父组件
Vue.component('my-cart', {
data: function() {
return {
list: [{
id: 1,
name: '手机',
price: 6000,
num: 1
}, {
id: 2,
name: '电脑',
price: 8000,
num: 1
}, {
id: 3,
name: '耳机',
price: 200,
num: 5
}, {
id: 4,
name: '充电宝',
price: 100,
num: 10
}]
}
},
template: `<div id="cart">
<cart-list :list="list" @cart-del="del($event)" @goods-num="changeNum($event)"></cart-list>
<cart-total :list="list"></cart-total>
</div>`,
components: {
'cart-list': cartList,
'cart-total': cartTotal
},
methods: {
del(i) {
this.list.splice(i, 1);
},
changeNum(e) {
if (e.type == 'inputChange') {
this.list[e.id].num = e.num;
} else if (e.type == 'addChange') {
this.list[e.id].num++;
} else {
if (this.list[e.id].num == 0) {
this.list[e.id].num = 0;
} else {
this.list[e.id].num--;
}
}
}
}
})
let vu = new Vue({
el: '#app',
data: {}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.5/vue.js"></script>
<title>购物车案例</title>
<style>
.cart {
width: 300px;
margin: auto;
}
.cart .title {
background-color: rgb(252, 11, 240);
height: 40px;
line-height: 40px;
color: white;
text-align: center;
}
.cart .item {
/* 子绝对位置父相对位置 */
position: relative;
height: 55px;
line-height: 55px;
border-top: 1px dashed rgb(116, 21, 103);
}
.cart .item:first-child {
border-top: none;
}
.cart .item img {
width: 45px;
height: 45px;
margin: 5px;
}
.cart .item .name {
position: absolute;
left: 55px;
top: 0;
font-size: 16px;
}
.cart .item .change {
position: absolute;
top: 0;
right: 50px;
width: 100px;
}
.cart .item .change a {
font-size: 20px;
text-decoration: none;
display: inline-block;
height: 25px;
width: 20px;
line-height: 25px;
background-color: lightgray;
text-align: center;
vertical-align: middle;
}
.cart .item .change .num {
width: 40px;
height: 25px;
}
.cart .item .del {
position: absolute;
top: 0;
right: 0;
width: 50px;
font-size: 28px;
text-align: center;
color: red;
}
.cart .total {
background-color: rgb(116, 21, 103);
height: 50px;
line-height: 50px;
text-align: right;
color: white;
}
.cart .total .account {
margin: 0 10px;
}
</style>
</head>
<body>
<div id="app">
<!--将组件渲染到页面上,定义组件名时,如果是用的驼峰命名,页面这里的组件名用短横线连接两个小写单词。-->
<my-cart></my-cart>
</div>
<script>
const cartTitle = {
//
props: ["uname"],
//注意:template创建的模板有且只有一个根元素。
template: `
<div class="title">{{uname}}的商品</div> `,
};
const cartList = {
props: ["list"],
//click.prevent阻止默认行为
template: `
<div>
<div class="item" v-for="ii in list" :key="ii.id">
<img :src="ii.img">
<div class="name">{{ii.name}}</div>
<div class="change">
<a href="" @click.prevent="$emit('change-num',{id:ii.id,type:'sub'})">-</a>
<input type="text" class="num" v-model="ii.num" @blur="$emit('change-num',{id:ii.id,type:'edit',num:$event.target.value})">
<a href="" @click.prevent="$emit('change-num',{id:ii.id,type:'add'})">+</a>
</div>
<div class="del" @click="$emit('del',ii.id)">X</div>
</div>
</div>
`,
};
const cartTotal = {
props: ["list"],
template: `
<div class="total">
<span>总价:{{total}}</span>
<input type="button" value="结算" class="account">
</div>
`,
//计算属性,进行累加和
computed: {
total() {
return this.list.reduce((sum, item) => {
return item.num * item.price + sum;
}, 0);
},
},
};
//定义全局组件
Vue.component("myCart", {
template: `
<div class="cart">
<cart-title :uname="uname"></cart-title>
<cart-list :list="goods" @change-num='changeNum' @del="delItem"></cart-list>
<cart-total :list="goods"></cart-total>
</div>
`,
components: {
cartTitle,
cartList,
cartTotal,
},
methods:{
delItem(id){
console.log("del");
this.goods=this.goods.filter(item=>{
return item.id!==id;
})
},
//先找到id,
changeNum(arg){
console.log(arg);
let id=arg.id;
let type=arg.type;
if(type==='add'){
this.goods.some(item=>{
if(item.id===id){
item.num++;
return true;
}
})
}else if(type==='sub'){
this.goods.some(item=>{
if(item.id===id){
if(item.num>=2){
item.num--;
}else{
//删除
this.delItem(id);
}
return true;
}
})
}else if(type==='edit'){
this.goods.some(item=>{
if(item.id===id){
item.num=arg.num;
return true;
}
})
}
}
},
data() {
return {
uname: "张三",
goods: [
{
id: 1,
name: "TCL彩电",
price: 1000,
num: 1,
img: "img/a.jpg",
},
{
id: 2,
name: "机顶盒",
price: 1000,
num: 1,
img: "img/b.jpg",
},
{
id: 3,
name: "海尔冰箱",
price: 1000,
num: 1,
img: "img/c.jpg",
},
{
id: 4,
name: "小米手机",
price: 1000,
num: 1,
img: "img/d.jpg",
},
{
id: 5,
name: "PPTV电视",
price: 1000,
num: 2,
img: "img/e.jpg",
},
],
};
},
});
const vm = new Vue({
el: "#app",
});
</script>
</body>
</html>