第一步建立一个组件的布局
上面部分划为3部分的组件块,第一部分标题,第二部分内容,第三部分结算
实现步骤
- 实现整体布局和样式效果
- 划分独立的功能组件
- 组合所有的子组件形成整体结构
- 逐个实现各个组件功能
具体代码如下
<body>
<div id="app">
<div class="container">
<my-cart></my-cart>
</div>
</div>
<script src="../../js/vue.js"></script>
<script type="text/javascript">
var CartTitle = {
template: `
<div class="title">我的商品</div>
`
};
var CartList = {
template: `
<div>
<div class="item">
<img src="../img/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="../img/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="../img/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="../img/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="img/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>
`
}
var CartTotal = {
template: `
<div class="total">
<span>总价:123</span>
<button>结算</button>
</div>
`
}
Vue.component('my-cart',{
template: `
<div class='cart'>
<cart-title></cart-title>
<cart-list></cart-list>
<cart-total></cart-total>
</div>
`,
components: {
'cart-title': CartTitle,
'cart-list': CartList,
'cart-total': CartTotal
}
});
var vm = new Vue({
el: '#app',
data: {
}
});
</script>
</body>
css样式
<style type="text/css">
.container {
}
.container .cart {
width: 300px;
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;
}
</style>
第二步利用组件化的思想实现以下功能
- 实现标题的显示
- 实现数据的显示
- 删除数据功能
- 实现加减
- 更新数量num,失去焦点的时候改变数量(同时价格也改变)
1.实现标题的显示
在父组件设置一些数据
Vue.component('my-cart',{
data:function(){
return{
name:'张三',//这是标题名字
list:[
{
id:1,name:'手机',peice:1200,num:2,img:'../img/a.jpg'},
{
id:2,name:'电脑',peice:11200,num:4,img:'../img/b.jpg'},
{
id:3,name:'机顶盒',peice:200,num:5,img:'../img/c.jpg'},
{
id:4,name:'1手机',peice:1200,num:1,img:'../img/d.jpg'},
{
id:5,name:'海尔',peice:1800,num:3,img:'../img/e.jpg'},
]
}
},
然后绑定
<div class='cart'>
<cart-title :name="name"></cart-title>
子组件接受数据
var CartTitle = {
props:['name'],
template: `
<div class="title">{
{name}}的商品</div>
`
};
2.实现标数据的显示
在CartList子组件中利用v-for遍历list的数据(切记要绑定数据)
var CartList = {
props:['list'],
template: `
<div>
<div v-for="item in list" :key="item.id" class="item">
<img :src="item.img"/>
<div class="name">{
{
item.name}}</div>
3.实现删除数据
首先找到每一项的索引,根据索引删除
delcart(id) {
//找到id的索引
var index=this.list.findIndex(item=>{
return item.id == id;
})
this.list.splice(index,1);
},
4。更新数量num和实现加减
首先在子组件中定义,计算结果在父组件中运算
gen(val){
this.list.some(item=>{
if (item.id == val.id) {
item.num=val.num ;
return true;
}
//终止遍历
})
},
sub(val){
this.list.some(item=>{
if (item.id == val.id) {
item.num -=1;
return true;
}
//终止遍历
})
},
add(val){
this.list.some(item=>{
if (item.id == val.id) {
item.num +=1;
return true;
}
//终止遍历
})
}
最终效果:
整合代码:
<div id="app">
<div class="container">
<my-cart></my-cart>
</div>
</div>
<script src="../../js/vue.js"></script>
<script type="text/javascript">
var CartTitle = {
props:['name'],
template: `
<div class="title">{
{name}}的商品</div>
`
};
var CartList = {
props:['list'],
template: `
<div>
<div v-for="item in list" :key="item.id" class="item">
<img :src="item.img"/>
<div class="name">{
{item.name}}</div>
<p>价格{
{item.peice}}</p>
<div class="change">
<a href="" @click.prevent="sub(item.id)">-</a>
<input type="text" class="num" :value="item.num" @blur="changenum(item.id,$event)"/>
<a href="" @click.prevent="add(item.id)">+</a>
</div>
<div class="del" @click="del(item.id)">×</div>
</div>
`,
methods:{
del(id){
this.$emit('cart-del',id);//把id给父组件
//应该把处理结果给父组件
},
changenum(id,event){
this.$emit('cart-changenum',{
id:id,
num:event.target.value
})
},
sub(id){
this.$emit('cart-sub',{
id:id
});//把id给父组件
},
add(id){
this.$emit('cart-add',{
id:id
});//把id给父组件
}
}
}
var CartTotal = {
props:['list'],
template: `
<div class="total">
<span>总价:{
{ total}}</span>
<button>结算</button>
</div>
`,
computed:{
total:function () {
var t=0;//总价
this.list.forEach(item =>{
t+=item.peice*item.num;
});
return t;
}
}
}
Vue.component('my-cart',{
data:function(){
return{
name:'张三',
list:[
{id:1,name:'手机',peice:1200,num:2,img:'../img/a.jpg'},
{id:2,name:'电脑',peice:11200,num:4,img:'../img/b.jpg'},
{id:3,name:'机顶盒',peice:200,num:5,img:'../img/c.jpg'},
{id:4,name:'1手机',peice:1200,num:1,img:'../img/d.jpg'},
{id:5,name:'海尔',peice:1800,num:3,img:'../img/e.jpg'},
]
}
},
template: `
<div class='cart'>
<cart-title :name="name"></cart-title>
<cart-list :list="list" @cart-del="delcart($event)" @cart-changenum="gen($event)" @cart-sub="sub($event)"
@cart-add="add($event)"
></cart-list>
<cart-total :list="list"></cart-total>
</div>
`,
components: {
'cart-title': CartTitle,
'cart-list': CartList,
'cart-total': CartTotal
},
methods: {
delcart(id) {
//找到id的索引
var index=this.list.findIndex(item=>{
return item.id == id;
})
this.list.splice(index,1);
},
gen(val){
this.list.some(item=>{
if (item.id == val.id) {
item.num=val.num ;
return true;
}
//终止遍历
})
},
sub(val){
this.list.some(item=>{
if (item.id == val.id) {
item.num -=1;
return true;
}
//终止遍历
})
},
add(val){
this.list.some(item=>{
if (item.id == val.id) {
item.num +=1;
return true;
}
//终止遍历
})
}
}
});
var vm = new Vue({
el: '#app',
data: {
}
});
</script>
感觉组件化这样写比较麻烦,但是遇到比较大的东西时可能比较复杂吧,
这个案例的知识点有
(1)父组件向子组件传值(props传递数据原则:单向数据流)
首先在父组件定义数据和绑定数据
然后子组件利用 props传递数据获取父组件的数据
(2)子组件向父组件传值
子组件通过$emit把数据给父组件
父组件通过$event数据
(3)event.target.value代表最新的值