今日总结,购物车计算与赛贝尔曲线动画

<template>
    <div>
		<div class="shopCart">
			<div class="left">
				<div class="cart">
			<img src="./img/cart.png" alt="" />
			<div class="num" v-show="totalCount>0">{{totalCount}}</div>
				</div>
			<p>¥{{totalPrice}}</p>
			</div>
		      <div class="ball-container">
		        <div v-for="ball in balls">
		          <transition name="drop" @before-enter="beforeDrop" @enter="dropping" @after-enter="afterDrop">
		            <div class="ball" v-show="ball.show">
		              <div class="inner inner-hook"></div>
		            </div>
		          </transition>
		        </div>
		      </div>
				<!--小球动画-->
			<div class="right">
				去结算
			</div>
		</div>	
    </div>
</template>

//底部购物车

<buycart :selectFoods="selectFoods"></buycart>
		<!--底部购物车-->
    </div>
</template>
<script>
	import BScroll from 'better-scroll'
	import buycart from './buyCart'

//载入与放置

   props: {
      selectFoods: {
        type: Array,
        default() {
          return [
            {
              price: 10,
              count: 1
            }
          ];
        }
      },
        },

//计算与获取 相关数据 比如价格啥的  从父组件那拿值 拿数组 后面会写

	    totalPrice() {
	        let total = 0;
	        this.selectFoods.forEach((food) => {
	          total += food.price * food.count;
	        });
	        return total;
	    			},
	    //计算总值
		totalCount() {
	        let count = 0;
	        this.selectFoods.forEach((food) => {
	          count += food.count;
	        });
	        return count;
	    			 },
	    //计算总数
    			}

//computed里的属性计算  selectfoods使用的是从上个页面传过来的值  后面会写出来

			<div class="left">
				<div class="cart">
			<img src="./img/cart.png" alt="" />
			<div class="num" v-show="totalCount>0">{{totalCount}}</div>
				</div>
			<p>¥{{totalPrice}}</p>
			</div>

//将值放入    购物车页结束。。     selectsfoods与food.cound  后面会写入

<template>
  <div class="cartcontrol">
    <transition name="move">
      <div class="cart-decrease">
        <div class="inner"  @click.stop.prevent="decreaseCart" v-show="food.count > 0">-</div>
      </div>
    </transition>
    <div class="cart-count" v-show="food.count > 0">{{food.count}}</div>
    <div class="cart-add"  @click.stop.prevent="addCart">+</div>
  </div>
</template>

//购物车控制页

<li style="display: flex;padding: 0.5rem 0;border-bottom: 1px solid #ccc;" v-for="items in item.shop_goods">
<img v-lazy='"http://jujiewang.oss-cn-hangzhou.aliyuncs.com/"+items.main_image' alt="" />
<div class="content">
<p class="name">{{items.goodname}}</p>
<p class="price">{{items.price}}/份</p>
<p class="tree">送{{items.orange}}颗桔树</p>
<div class="cartcontrol-wrapper">
<cartcontrol :food="items" @add="addFood"></cartcontrol>
</div>
<!--购物车+-按钮-->
</div>
</li>

//将foods值传入  传入的是循环的自己的数组

    computed: {
	    totalPrice() {
	        let total = 0;
	        this.selectFoods.forEach((food) => {
	          total += food.price * food.count;
	        });
	        return total;
	    			},
	    //计算总值
		totalCount() {
	        let count = 0;
	        this.selectFoods.forEach((food) => {
	          count += food.count;
	        });
	        return count;
	    			 },
	    //计算总数
    			}
  };

//点击+1-1 因为用了betterscroll 要先在上层允许点击  click: true 即用到betterscroll的区域  

      selectFoods() {
        let foods = [];
        if(this.goods.respond){
        this.goods.respond.forEach((good) => {
          good.shop_goods.forEach((food) => {
            if (food.count) {
              foods.push(food);
            }
         		});
        });
        return foods;
       //加个判断防止forEach报错
        						}
      			    }

// 放入计算属性   给购物车循环出来的 上面写到的

<buycart :selectFoods="selectFoods" ref="shopcart" ></buycart>

//将selectFoods的值传入  结束  购物车与 + - 计算

    data() {
      return {
        balls: [            // 5个小球 解决在前一个小球没有下落后又点击的问题
          {
            show: false
          },
          {
            show: false
          },
          {
            show: false
          },
          {
            show: false
          },
          {
            show: false
          }
        ],
        dropBalls: [],
        fold: true       // 默认折叠
      };
    },
    //小球动画

//传给动画值

<div class="ball-container">
<div v-for="ball in balls">
<transition name="drop" @before-enter="beforeDrop" @enter="dropping" @after-enter="afterDrop">
<div class="ball" v-show="ball.show">
<div class="inner inner-hook"></div>
</div>
</transition>
</div>
</div>
//html
				    .ball-container {
				      .ball {
				        position: fixed;
				        left: 32px;
				        bottom: 22px;
				        z-index: 200;
				        .inner {
				          width: 16px;
				          height: 16px;
				          border-radius: 50%;
				          background: #FF9500;
				        }
				        &.drop-enter-active {
				          transition: all .4s cubic-bezier(.49, -0.29, .75, .41);
				          .inner {
				            transition: all .4s linear;
				          }
				        }
				      }
				    }
					/*小球样式*/

//放入小球样式与html

this.$emit('add', event.target);      // 触发当前实例上的事件,以便父元素@监听子元素。将点击的元素传入

//监听点击事件

dropBalls: [],

//存入数组控制

      drop(el) {   // 拿到cartcontrol点击的元素
        for (let i = 0; i < this.balls.length; i++) {
          let ball = this.balls[i];
          if (!ball.show) {   // 循环所有ball,找出未show
            ball.show = true;
            ball.el = el;
            this.dropBalls.push(ball);
            return;
          }
        }
      },

//给与显示

    <div class="inner inner-hook"></div>

//放入控制值

    drop(el) {   // 拿到cartcontrol点击的元素
        for (let i = 0; i < this.balls.length; i++) {
          let ball = this.balls[i];
          if (!ball.show) {   // 循环所有ball,找出未show
            ball.show = true;
            ball.el = el;
            this.dropBalls.push(ball);
            return;
          }
        }
      },
      // 小球执行步骤:
      // 1. 点击cartcontrol组件中的”加号按钮“,$emit添加触发事件,将event.target作为参数,由goods父组件监听
      // 2. goods组件接收事件和target,执行_drop(target),调用shopcart子组件的drop(el)方法,传入了target
      // 3. shopcart 组件执行 drop(el) 方法时,获取el在视口中的位置,编程式调用ball元素的过渡hook接口,执行css过渡
      // 过渡 钩子
      // 动画的原理是先把它偏移到一个位置,然后按照一定的轨迹和时间完成动画,动画完成后要把位置重置
      	beforeDrop(el) {    // el 是Vue 钩子选择作用动画的 DOM 对象
        	let count = this.balls.length;
        	while (count--) {
          let ball = this.balls[count];
          if (ball.show) {
            let rect = ball.el.getBoundingClientRect(); // 得到元素距视口各边的偏移量
            // 是相对于小球初始位置的,所以 x 是正的,y 是负的
            let x = rect.left - 32;
            let y = -(window.innerHeight - rect.top - 36);
            el.style.display = '';        // 手动设置为空,小球会显示出来
            el.style.webkitTransform = `translate3d(0,${y}px,0)`;
            el.style.transform = `translate3d(0,${y}px,0)`;
            let inner = el.getElementsByClassName('inner-hook')[0];   // 获取当前el的innerDom节点
            inner.style.webkitTransform = `translate3d(${x}px,0,0)`;
            inner.style.transform = `translate3d(${x}px,0,0)`;
          }
        				  }
      					},
      	//之前跌落
      dropping(el, done) {  // Vue enter 的第二个参数必须给,否则会设置成同步
        /* eslint-disable no-unused-vars */
        let rf = el.offsetHeight;
        // 触发浏览器重绘,可以保证 dom 位置渲染正确后再执行之后的动画
        this.$nextTick(() => {
          el.style.webkitTransform = 'translate3d(0,-10px,0)';
          el.style.transform = 'translate3d(0,-10px,0)';
          let inner = el.getElementsByClassName('inner-hook')[0];
          inner.style.webkitTransform = 'translate3d(0,0,0)';
          inner.style.transform = 'translate3d(0,0,0)';
          // 告知Vue,一个小球动画完成
          el.addEventListener('transitionend', done);   // 当动画结束,会有  CSS3 transitionend 事件派发
        					});
      					},
     afterDrop(el) {
        // 首先触发afterDrop是最先落的小球,所以把第一项也就是先落的小球重置
        let ball = this.dropBalls.shift();    // 删除dropBalls第一项,并返回此项
        if (ball) {
          ball.show = false;
          el.style.display = 'none';
        }
     				},
		//小球动画

//给予小球动画   我也不懂啊啊啊啊啊啊啊啊 啊啊

猜你喜欢

转载自blog.csdn.net/qq_38674970/article/details/81260206