Vue基础案例三:购物车(组件化思想练习)

实现效果:
在这里插入图片描述
1.原始布局:

<div id="app">
   <div class="container">
       <div class='cart'>
           <!--1 头部标题 -->
           <div class="title">我的商品</div>
           <!--2 中间列表 -->
           <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>
           <!--3 尾部结算 -->
           <div class="total">
               <span>总价:123</span>
               <button>结算</button>
           </div>
       </div>
   </div>
</div>

2.运用组件化思想划分独立的功能组件
js:

<script type="text/javascript">
    //以下三个子组件都是局部组件
    //子组件1:标题
    var CartTitle = {
            template: `
		    <div class="title">我的商品</div>
		  `
        }
        //子组件2:列表
    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>
		  `
        }
        //子组件3:计算总价
    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>

html:

<div id="app">
   <div class="container">
        <my-cart></my-cart>
    </div>
</div>

3.完成标题、列表、结算组件的数据展示(父组件向子组件传值)

//父组件
Vue.component('my-cart', {
     //步骤一:在父组件中添加数据
	 data: function() {
	         return {
	             puname: '张三',
	             plist: [{
	                 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'
	             }]
	         }
	     },
	     //模板串
	     template: `
		 <div class='cart'>
		   <!-- 步骤二: 子组件绑定父组件的属性值-->
		   <cart-title :uname='puname'></cart-title>
		   <cart-list :list='plist'></cart-list>
		   <cart-total :list='plist'></cart-total>
		 </div>
		`,
	     //它的三个子组件
	     components: {
	         'cart-title': CartTitle,
	         'cart-list': CartList,
	         'cart-total': CartTotal
	     }
	 });

    //子组件1:标题
    var CartTitle = {
            //步骤三:子组件用props接收数据
            props: ['uname'],
            template: `
            <!-- 步骤四: 使用接收的数据-->
             <div class="title" >{{uname}}的商品</div>
            `
            }
            
       //子组件2:列表
        var CartList = {
            props: ['list'],
                template: `
		        <div>
		          <!--循环遍历list-->
		          <div class="item" :key='item.id' v-for='item in list'>
		            <img :src="item.img"/>
		            <div class="name">{{item.name}}</div>
		            <div class="change">
		              <a href="">-</a>
		              <input type="text" class="num" :value='item.num'/>
		              <a href="">+</a>
		            </div>
		            <div class="del">×</div>
		          </div>           
		        </div>
		      `
       }
       
    //子组件3:尾部结算
	var CartTotal = {
	      props: ['list'],
	      template: `
	        <div class="total">
	          <span>总价:{{sum}}</span>
	          <button>结算</button>
	        </div>
	      `,
	      //计算属性
	      computed: {
	        sum: function() {
	          // 计算商品的总价
	          var t = 0;
	          this.list.forEach(item => {
	            t += item.price * item.num;
	          });
	          return t;
	        }
	      }
	    }

4.删除(子组件向父组件传值)
需求:点击删除按钮,根据item.id找到item在list中的index,再进行删除

注意:数据的定义和操作都要求在父组件中进行,子组件只负责展示。这里的删除操作页面上处于子组件中,所以要向父组件传值,在父组件中进行操作数据。

//子组件2:列表
  var CartList = {
      props: ['list'],
          template: `
    <div>
      <!--循环遍历list-->
      <div class="item" :key='item.id' v-for='item in list'>
        <img :src="item.img"/>
        <div class="name">{{item.name}}</div>
        <div class="change">
          <a href="">-</a>
          <input type="text" class="num" :value='item.num'/>
          <a href="">+</a>
        </div>
        <!--步骤一:子组件的点击事件(传递item.id)-->
        <div class="del" @click='del(item.id)'>×</div>
      </div>           
    </div>
  `,
    methods: {
         del: function(id) {
             //步骤二:通过$emit(arg1,arg2)触发事件
             // 把id传递给父组件
             //参数1:事件名称,参数二:要传递的数据
             this.$emit('cart-del', id);
         }
     }
 }

//父组件
Vue.component('my-cart', {
    data:{...省略..},
       //模板串
       template: `
		   <div class='cart'>
		     <cart-title :uname='puname'></cart-title>
		     <!--步骤三:父组件用 v-on:arg1或者@arg1 监听子组件的事件cart-del-->
		     <cart-list :list='plist' @cart-del='delCart($event)'></cart-list>
		     <cart-total :list='plist'></cart-total>
		   </div>
		 `,
       //它的三个子组件
       components: {...省略..},
       methods: {
           delCart: function(id) {
               // 根据id删除plist中对应的数据
               // 1、找到id所对应数据的索引
               var index = this.plist.findIndex(item => {
                   return item.id == id;
               });
               // 2、根据索引删除对应数据
               this.plist.splice(index, 1);
           }
       }
   });

5.列表组件中数量 (item.num) 更新后,总价格相应发生变化(子组件向父组件传值)

//子组件2:列表
  var CartList = {
      props: ['list'],
          template: `
    <div>
      <div class="item" :key='item.id' v-for='item in list'>
        <img :src="item.img"/>
        <div class="name">{{item.name}}</div>
        <div class="change">
          <a href="">-</a>
          <!--步骤一:为子组件中的input输入框添加失去焦点事件(传递item.id和事件event,这里通过event拿到input的值value)-->
          <input type="text" class="num" :value='item.num' @blur='changeNum(item.id, $event)'/>
          <a href="">+</a>
        </div>
        <div class="del" @click='del(item.id)'>×</div>
      </div>           
    </div>
  `,
    methods: {
        //步骤二:子组件中通过$emit(arg1,arg2)触发事件,向父组件传递信息
	    changeNum: function(id, event){
			    //event.target得到input标签
		        // console.log(id, event.target.value);
	          this.$emit('change-num', {
	            id: id,
	            num: event.target.value
	          });
	        }
     }
 }

//父组件
Vue.component('my-cart', {
    data: {...省略..},
       //模板串
       template: `
		   <div class='cart'>
		     <cart-title :uname='puname'></cart-title>
		     <!--步骤三:父组件中用 v-on:arg1或者@arg1 监听子组件的事件change-num,参数$event接收值-->
		     <cart-list :list='plist' @change-num='changeNum($event)'  @cart-del='delCart($event)'></cart-list>
		     <cart-total :list='plist'></cart-total>
		   </div>
		 `,
       //它的三个子组件
       components: {...省略..},
       methods: {
           //步骤四:父组件处理
	       changeNum: function(val) {
	          // 根据子组件传递过来的数据,更新plist中对应的数据
	          this.plist.some(item=>{
	          //如果plist中某一项的id(item.id)等于 输入这一项的id(val.id)
	            if(item.id == val.id) {
	              item.num = val.num;//修改数量值item.num
	              // 终止遍历
	              return true;
	            }
	          });
	        }
       }
   });

6.列表组件中加减数量相关操作(子组件向父组件传值)

//子组件2:列表
  var CartList = {
      props: ['list'],
          template: `
    <div>
      <div class="item" :key='item.id' v-for='item in list'>
        <img :src="item.img"/>
        <div class="name">{{item.name}}</div>
        <div class="change">
          <!--步骤一:为子组件中的加减a标签添加点击事件(传递item.id),并用事件修饰符.prevent阻止默认行为-->
          <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>           
    </div>
  `,
    methods: {
        //步骤二:子组件中通过$emit(事件名称,参数)触发事件,向父组件传递信息
	   sub: function(id) {
             console.log(id);
             this.$emit('cart-one', {
                 //传递的两个参数(对象形式)
                 id: id,
                 step: -1
             });
         },
         add: function(id) {
             console.log(id);
             this.$emit('cart-one', {
                 id: id,
                 step: 1
             });
         }
     }
 }

//父组件
Vue.component('my-cart', {
    data: {...省略..},
       //模板串
       template: `
		   <div class='cart'>
		     <cart-title :uname='puname'></cart-title>
		     <!--步骤三:父组件中用 v-on:arg1或者@arg1 监听子组件的事件cart-one,参数$event接收值-->
		     <cart-list :list='plist' @cart-one='cartOne($event)'  @change-num='changeNum($event)'  @cart-del='delCart($event)'></cart-list>
		     <cart-total :list='plist'></cart-total>
		   </div>
		 `,
       //它的三个子组件
       components: {...省略..},
       methods: {
           //步骤四:父组件处理
	       cartOne: function(val) {
                    console.log('---------');
                    console.log(val);
                    this.plist.some(item => {
                        if (item.id == val.id) {
                            item.num += val.step;
                            // 终止遍历
                            return true;
                        }
                    });
                }
       }
   });
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值