1.1 组件综合案例讲解-购物车
前面我们学了组件,我们也知道Vue的核心是组件系统和数据驱动,下面我们来做一个购物车的案例,巩固深化一下我们所学的理论知识
效果预览:
1.1.1 组件化布局组件拆分
-
把静态页面转换为组件化模式
-
把组件渲染到页面上显示效果如下所示
代码效果如下:
<script src="./js/vue.js"></script>
<script>
//创建子组件
//标题组件
let cartTitle={
template:'#cart-title',
props:['title']
}
//商品列表组件
let cartList={
template:'#cart-list',
props:['good_list'],
}
//结算组件
let cartTotal={
template:'#cart-total'
},
//全局组件(父组件)
Vue.component('my-cart',{
template:'#my-cart',
data(){
return{
title:'我的产品',
good_list:[
{
id:1,
name:'电视',
price:2999,
num:1,
img:'./img/01.png'
},
{
id:2,
name:'机顶盒',
price:1500,
num:1,
img:'./img/02.png'
},
{
id:3,
name:'扫地机器人',
price:1299,
num:1,
img:'./img/03.png'
},
{
id:4,
name:'数码相机',
price:1000,
num:1,
img:'./img/04.png'
},
{
id:5,
name:'笔记本',
price:3896,
num:1,
img:'./img/05.png'
},
]
}
},
components:{
cartTitle,cartList,cartTotal
}
//根组件
var vm=new Vue({
//模板选择器
el:'#app',
//数据中心
data(){
return{
}
},
methods:{
}
})
1.1.2完成标题和结算组件功能 组件传值
-
标题组件事件动态渲染
-
从父组件把标题数据传递过来 即 父向子组件传值
-
把传递过来的数据渲染到页面上
-
-
结算功能组件
-
从父组件把商品列表list 数据传递过来 即 父向子组件传值
-
把传递过来的数据计算最终价格渲染到页面上
-
<div id="app">
<my-cart></my-cart>
</div>
<template id="cart-title">
<div>
{{title}}
</div>
</template>
<template id="cart-list">
<div>
<table width="800">
<tr>
<th>商品编号</th>
<th>商品名称</th>
<th>商品图片</th>
<th>商品价格</th>
<th>商品数量</th>
<th>操作商品</th>
</tr>
<tr v-for="(item,index) in good_list">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td><img :src="item.img" alt="" width="123"></td>
<td>{{item.price}}</td>
<td>
<button @click="reduce(item.id)">-</button>
<input type="text" :value="item.num" @blur="sj(item.id,$event)">
<button @click="plus(item.id)">+</button>
</td>
<td>
<button @click="del(item.id)">删除</button>
</td>
</tr>
</table>
</div>
</template>
<template id="cart-total"></template>
<template id="my-cart">
<div>
<cart-title :title="title"></cart-title>
<cart-list :good_list="good_list" @cart-del="removeGood" @change-num="changeNums" ></cart-list>
<cart-total :total1="good_list"></cart-total>
</div>
</template>
//结算组件
let cartTotal={
template:'#cart-total',
props:['total1'],
computed:{
total(){
let amount=0;
//遍历
this.total1.forEach(item=>{
amount+=item.price*item.num
})
return amount.toFixed(2)
}
}
}
分析:
父组件 向 标题组件(子组件)传值,思路分析:
1.1.3 完成列表组件删除商品功能splice
-
从父组件把商品列表list 数据传递过来 即 父向子组件传值
-
把传递过来的数据渲染到页面上
-
点击删除按钮的时候删除对应的数据
-
子组件中不推荐操作父组件的数据,有可能多个子组件使用父组件的数据,我们需要把数据 传递给父组件 让父组件操作数据
-
父组件删除对应的数据
-
给按钮添加点击事件把需要删除的id传递过来
-
//商品列表组件
let cartList={
template:'#cart-list',
props:['good_list'],
methods:{
del(id){
//删除
//子传父
this.$emit('cart-del',id)
},
//全局组件(父组件)
Vue.component('my-cart',{
template:'#my-cart',
methods:{
removeGood(){
console('父组件接收到子组件传递过来的值')
console(id);
let index=this.good_list.findIndex(item=>item.id=id)
}
}
1.1.4 完成列表组件更新商品数量computed
-
将输入框中的默认数据动态渲染出来
-
输入框失去焦点的时候 更改商品的数量
-
点击按钮+和按钮-更新商品的数量,同步更新总价格
-
子组件中不推荐操作数据 把这些数据传递给父组件 让父组件处理这些数据
-
父组件中接收子组件传递过来的数据并处理
//商品列表组件
let cartList={
template:'#cart-list',
props:['good_list'],
methods:{
del(id){
//删除
//子传父
this.$emit('cart-del',id)
},
//失去焦点blur事件中的方法
sj(id){
this.$emit('change-num',{id:id,type:'change',num:event.target.value})
console.log(event.target.value)
},
//click单击事件中的方法
reduce(id){
//减
//change-num:给父组件my-cart中自定义事件,并传值
this.$emit('change-num',{id:id,type:'reduce'})
},
plus(id){
//加
this.$emit('change-num',{id:id,type:'plus'})
}
}
}
//全局组件(父组件)
Vue.component('my-cart',{
template:'#my-cart',
methods:{
changeNums(data){
console.log(data);
var id=data.id
console.log(id);
let index=this.good_list.findIndex(item=>item.id==id);
console.log(index);
if(data.type=='plus'){
this.good_list[index].num++
}
if(data.type=='reduce'){
this.good_list[index].num--;
if(this.good_list[index].num<0){
this.good_list[index].num=0;
return
}
}
if(data.type=='change'){
this.good_list[index].num=data.num
}
}
},
}