vuejs2-5 goods页面

1 goods.vue组件功能(当未使用其他组件时)

1.1 src/App.vue 传递值

<keep-alive>
      <router-view :seller="seller"></router-view>
</keep-alive>

1.2 src/components/goods.vue

<template>
  <div>
    <div class="goods">
      <!--左侧分类-->
      <div class="menu-wrapper" ref="menuWrapper">
        <ul>
          <li v-for="(item,index) in goods" class="menu-item"
              :class="{'current':currentIndex===index}"
              @click="slectMenu(index,$event)">
            <span class="text border-1px">
              <span class="icon" v-show="item.type>0"
                    :class="classMap[item.type]"></span>
              {{item.name}}
            </span>
          </li>
        </ul>
      </div>
      <!--右侧商品列表-->
      <div class="foods-wrapper" ref="foodsWrapper">
        <ul>
          <li v-for="item in goods" class="foot-list food-list-hook" ref="foodList">
            <h2 class="title">{{item.name}}</h2>
            <ul>
              <li v-for="food in item.foods" class="foods-item border-1px" @click="selectFood(food,$event)">

                <div class="icon">
                  <img :src="food.icon" width="57" height="57">
                </div>

                <div class="content">
                  <h3 class="name">{{food.name}}</h3>
                  <p class="desc">{{food.description}}</p>
                  <div class="extra">
                    <span class="count">月售{{food.sellCount}}</span>
                    <span>好评率:{{food.rating}}%</span>
                  </div>
                  <div class="price">
                    <span class="now">¥{{food.price}}</span>
                    <span v-show="food.oldPrice" class="odd">¥{{food.oldPrice}}</span>
                  </div>
                </div>
              </li>
            </ul>
          </li>
        </ul>
      </div>
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
  import BScroll from 'better-scroll';

  const ERR_OK = 0; // 验证后台数据是否可用

  export default{
    props: { // 用来接收其他组件的数据
      seller: {
        type: Object
      }
    },
    data() { // 数据
      return {
        goods: [],
        listHeight: [],
        scrollY: 0,
        selectedFood: {}
      };
    },
    computed: { // 计算属性
      currentIndex() { // 右侧内容区滚动时左侧对应添加样式
        for (let i = 0; i < this.listHeight.length; i++) {
          let height1 = this.listHeight[i];
          let height2 = this.listHeight[i + 1];
          if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) { // 滚动高度大于或等于当前i区块的高度 小于i+1区块的高度
            return i;
          };
        };
        return 0; // 刚加载进来默认左侧第一个分类添加样式
      }
    },
    created() { // dom加载时的操作
      this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee'];
      // 请求获取goods的数据
      this.$http.get('/api/goods')
        .then((res) => {
          res = res.body;
          if (res.errno === ERR_OK) {
            this.goods = res.data;
            this.$nextTick(() => { // 保证dom渲染好后
              this._initScroll();
              this._calcullateHeight(); // 计算区间高度组成的数组
            });
          }
          ;
        });
    },
    methods: { // 方法
      _initScroll() {
        this.menuScroll = new BScroll(this.$refs.menuWrapper, {
          click: true // 可以点击
        });
        this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
          probeType: 3, // scroll滚动时监听滚动位置
          click: true
        });
        this.foodsScroll.on('scroll', (pos) => {
          this.scrollY = Math.abs(Math.round(pos.y));
          // console.log(this.scrollY);
        });
      },
      _calcullateHeight() { // 计算右侧内容各自分区的高度 添加到this.listHeight数组中
        // let foodList = this.$refs.foodsWrapper.getElementsByClassName('food-list-hook');
        let foodList = this.$refs.foodList; // 获得右侧li的dom集合
        let height = 0;
        this.listHeight.push(height);
        for (let i = 0; i < foodList.length; i++) {
          let item = foodList[i];
          height += item.clientHeight; // 每个区间累加后的高度
          this.listHeight.push(height); // 区间高度放到数组里面
        };
      },
      slectMenu(_index, ev) { // 点击左侧分类添加样式,右侧对应内容滚动到顶部
        if (!ev._constructed) { // 使用了BS
          return;
        };
        let foodList = this.$refs.foodList;
        let els = foodList[_index];
        this.foodsScroll.scrollToElement(els, 300);
      }
    }
  };
</script>

<style lang="stylus" rel="stylesheet/stylus">
  @import "../../common/stylus/mixin.styl"

  .goods
    $main_bg = #f3f5f7
    $line_bg = #d9dde1
    $bottom_bg = rgba(7,17,27,0.1)

    display:flex
    overflow:hidden
    position:absolute
    top:174px
    bottom:46px
    width:100%
    .menu-wrapper
      flex:0 0 80px
      width:80px
      background:$main_bg
      .menu-item
        display:table
        height:54px
        width:56px
        line-height:14px
        padding:0 12px
        &.current
          position:relative
          z-index:10
          margin-top: -1px
          background:#fff
          &:before
            content:''
            display:block
            width:4px
            height:100%
            position:absolute
            top:0
            left:0
            background-color:#00A0DC
          .text
            border-none()
            font-weight:700
      .text
        display:table-cell
        width:56px
        vertical-align:middle
        font-size:12px
        border-1px($bottom_bg)
        .icon
          display:inline-block
          width:12px
          height:12px
          margin-right:2px
          background-size:12px
          background-repeat:no-repeat
          &.decrease
            bg-img("decrease_3")
          &.discount
            bg-img("discount_3")
          &.invoice
            bg-img("invoice_3")
          &.special
            bg-img("special_3")
          &.guarantee
            bg-img("guarantee_3")

    .foods-wrapper
      flex:1
      .title
        height:26px
        background-color:$main_bg
        border-left:1px solid $line_bg
        text-indent:13px
        font-size:12px
        color:rgb(147,153,159)
        line-height:26px
      .foods-item
        display:flex
        margin:18px
        padding-bottom:18px
        border-1px($bottom_bg)
        &:last-child
          padding:0
          border-none()
        $:first-child
          .content
            .cartcontroll-wrapper
              bottom:5px
        .icon
          flex:0 0 57px
          margin-right:10px
          img
            border-radius:3px
        .content
          flex:1
          position:relative
          .name
            margin:2px 0 8px 0
            font-size:14px
            color:rgb(7,17,27)
            line-height:14px
            height:14px
          .desc,txtra
            font-size:10px
            color:rgb(147,153,159)
            line-height:10px
          .desc
            margin-bottom:8px
            line-height:12px
          .extra
            font-size:0px
            .count
              margin-right:12px
          .price
            .now,add
              line-height:24px
              font-weight:700
            .now
              font-size:14px
              color:rgb(240,20,20)
              margin-right:8px
            .odd
              font-size:10px
              color:rgb(147,153,159)
              text-decoration:line-through
          .cartcontroll-wrapper
              position:absolute
              bottom:-8px
              right:0


</style>

 

2 使用 shopcart.vue组件

2.1 未添加小球下落动画 src/components/goods.vue

<template>
  <div>
    <div class="goods">
      <!--左侧分类-->
      <div class="menu-wrapper" ref="menuWrapper">
        <ul>
          <li v-for="(item,index) in goods" class="menu-item"
              :class="{'current':currentIndex===index}"
              @click="slectMenu(index,$event)">
            <span class="text border-1px">
              <span class="icon" v-show="item.type>0"
                    :class="classMap[item.type]"></span>
              {{item.name}}
            </span>
          </li>
        </ul>
      </div>
      <!--右侧商品列表-->
      <div class="foods-wrapper" ref="foodsWrapper">
        <ul>
          <li v-for="item in goods" class="foot-list food-list-hook" ref="foodList">
            <h2 class="title">{{item.name}}</h2>
            <ul>
              <li v-for="food in item.foods" class="foods-item border-1px" @click="selectFood(food,$event)">

                <div class="icon">
                  <img :src="food.icon" width="57" height="57">
                </div>

                <div class="content">
                  <h3 class="name">{{food.name}}</h3>
                  <p class="desc">{{food.description}}</p>
                  <div class="extra">
                    <span class="count">月售{{food.sellCount}}</span>
                    <span>好评率:{{food.rating}}%</span>
                  </div>
                  <div class="price">
                    <span class="now">¥{{food.price}}</span>
                    <span v-show="food.oldPrice" class="odd">¥{{food.oldPrice}}</span>
                  </div>
                  <div class="cartcontroll-wrapper">
                    <cart-controll :food="food" ref="food"></cart-controll>
                  </div>
                </div>
              </li>
            </ul>
          </li>
        </ul>
      </div>
      <!--底部购物车-->
      <shop-cart ref="shopcart" :select-foods="selectFoods" :delivery-price="seller.deliveryPrice" :min-price="seller.minPrice"></shop-cart>
    </div>
  </div>
</template>

<script type="text/ecmascript-6">
  import BScroll from 'better-scroll';
   import shopcart from 'components/shopcart/shopcart';
    import cartcontroll from 'components/cartcontroll/cartcontroll';

  const ERR_OK = 0;

  export default{
    props: { // 用来接收其他组件的数据
      seller: {
        type: Object
      }
    },
    data() { // 数据
      return {
        goods: [],
        listHeight: [],
        scrollY: 0,
        selectedFood: {}
      };
    },
    computed: { // 计算属性
      currentIndex() { // 右侧内容区滚动时左侧对应添加样式
        for (let i = 0; i < this.listHeight.length; i++) {
          let height1 = this.listHeight[i];
          let height2 = this.listHeight[i + 1];
          if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) {
            return i;
          };
        };
        return 0;
      },
      selectFoods() { // 计算商品数量是否变化(可以监听到被cartcontroll.vue改变的food)
                      // 因为在使用cartcontroll.vue时传给它的就是food
                      // 将变化结果传递给shopcart.vue( :select-foods="selectFoods")
        let foods = [];
        this.goods.forEach((good) => {
          good.foods.forEach((food) => {
            if (food.count) { // 此时food的数量不为0说明已经被添加或减小更改了
              foods.push(food);
            }
          });
        });
        return foods;
      }
    },
    created() { // dom加载时的操作
      this.classMap = ['decrease', 'discount', 'special', 'invoice', 'guarantee'];
      // 请求获取goods的数据
      this.$http.get('/api/goods')
        .then((res) => {
          res = res.body;
          if (res.errno === ERR_OK) {
            this.goods = res.data;
            this.$nextTick(() => { // 保证dom渲染好后
              this._initScroll();
              this._calcullateHeight(); // 计算区间高度组成的数组
            });
          }
          ;
        });
    },
    methods: { // 方法
      _initScroll() {
        this.menuScroll = new BScroll(this.$refs.menuWrapper, {
          click: true // 可以点击
        });
        this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
          probeType: 3, // scroll滚动时监听滚动位置
          click: true
        });
        this.foodsScroll.on('scroll', (pos) => {
          this.scrollY = Math.abs(Math.round(pos.y));
          // console.log(this.scrollY);
        });
      },
      _calcullateHeight() { // 计算右侧内容各自分区的高度 添加到this.listHeight数组中
        // let foodList = this.$refs.foodsWrapper.getElementsByClassName('food-list-hook');
        let foodList = this.$refs.foodList; // 获得右侧li的dom集合
        let height = 0;
        this.listHeight.push(height);
        for (let i = 0; i < foodList.length; i++) {
          let item = foodList[i];
          height += item.clientHeight; // 每个区间累加后的高度
          this.listHeight.push(height); // 区间高度放到数组里面
        };
      },
      slectMenu(_index, ev) { // 点击左侧分类添加样式,右侧对应内容滚动到顶部
        if (!ev._constructed) { // 使用了BS
          return;
        };
        let foodList = this.$refs.foodList;
        let els = foodList[_index];
        this.foodsScroll.scrollToElement(els, 300);
      }
    },
    components: { // 注册组件
      shopCart: shopcart, // 底部购物车
      cartControll: cartcontroll // 增加减少
    }
  };
</script>

<style lang="stylus" rel="stylesheet/stylus">
  @import "../../common/stylus/mixin.styl"

  .goods
    $main_bg = #f3f5f7
    $line_bg = #d9dde1
    $bottom_bg = rgba(7,17,27,0.1)

    display:flex
    overflow:hidden
    position:absolute
    top:174px
    bottom:46px
    width:100%
    .menu-wrapper
      flex:0 0 80px
      width:80px
      background:$main_bg
      .menu-item
        display:table
        height:54px
        width:56px
        line-height:14px
        padding:0 12px
        &.current
          position:relative
          z-index:10
          margin-top: -1px
          background:#fff
          &:before
            content:''
            display:block
            width:4px
            height:100%
            position:absolute
            top:0
            left:0
            background-color:#00A0DC
          .text
            border-none()
            font-weight:700
      .text
        display:table-cell
        width:56px
        vertical-align:middle
        font-size:12px
        border-1px($bottom_bg)
        .icon
          display:inline-block
          width:12px
          height:12px
          margin-right:2px
          background-size:12px
          background-repeat:no-repeat
          &.decrease
            bg-img("decrease_3")
          &.discount
            bg-img("discount_3")
          &.invoice
            bg-img("invoice_3")
          &.special
            bg-img("special_3")
          &.guarantee
            bg-img("guarantee_3")

    .foods-wrapper
      flex:1
      .title
        height:26px
        background-color:$main_bg
        border-left:1px solid $line_bg
        text-indent:13px
        font-size:12px
        color:rgb(147,153,159)
        line-height:26px
      .foods-item
        display:flex
        margin:18px
        padding-bottom:18px
        border-1px($bottom_bg)
        &:last-child
          padding:0
          border-none()
        $:first-child
          .content
            .cartcontroll-wrapper
              bottom:5px
        .icon
          flex:0 0 57px
          margin-right:10px
          img
            border-radius:3px
        .content
          flex:1
          position:relative
          .name
            margin:2px 0 8px 0
            font-size:14px
            color:rgb(7,17,27)
            line-height:14px
            height:14px
          .desc,txtra
            font-size:10px
            color:rgb(147,153,159)
            line-height:10px
          .desc
            margin-bottom:8px
            line-height:12px
          .extra
            font-size:0px
            .count
              margin-right:12px
          .price
            .now,add
              line-height:24px
              font-weight:700
            .now
              font-size:14px
              color:rgb(240,20,20)
              margin-right:8px
            .odd
              font-size:10px
              color:rgb(147,153,159)
              text-decoration:line-through
          .cartcontroll-wrapper
              position:absolute
              bottom:-8px
              right:0


</style>

2.2 添加小球下落动画

2.2.1 src/components/goods.vue

<div class="cartcontroll-wrapper">
                    <cart-controll :food="food" @add="addFood"></cart-controll>
</div>

methods:
// 小球相关
      addFood(target) { //获得cart-controll.vue 点击的对象 可以获得的原因 1传递了add事件 2 $emit这个对象
        this._drop(target);
      },
      _drop(target) {
        this.$nextTick(() => { // 体验优化,异步执行下落动画
          this.$refs.shopcart.drop(target); // 访问子组件shopcart.vue
        });
      }

 

3 src/components/cartcontroll.vue组件(增加时旋转和平移)

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

  </div>
</template>

<script type="text/ecmascript-6">
  import Vue from 'vue';

  export default {
    props: { // 接收其他组件传递过来的数据
      food: {
        type: Object
      }
    },
    methods: { // 指令方法
      addCart: function(ev) { // 增加商品到购物车里
        if (!ev._constructed) { // 去掉触发pc的事件--保证pc移动事件相同
          return false;
        };
        if (!this.food.count) {
          // this.food.count = 1; 不生效
          Vue.set(this.food, 'count', 1); // 此时这个属性变化就能被观测到
        } else {
          this.food.count++;
        };
        // this.$dispatch('cart.add', ev.target); 2.0- 已被废除
        this.$emit('add', event.target); // 触发当前实例上的事件。附加参数都会传给监听器回调。event.target点击的按钮的dom
      },
      decreaseCart: function (ev) { // 减少购物车里面商品的数量
        if (!ev._constructed) {
          return false;
        };
        if (this.food.count) {
          this.food.count--;
        };
      }
    }
  };
</script>

<style lang="less" rel="stylesheet/less">
  .cartcontroll{
    font-size:0px;
    .cart-decrease{ /*该层负责平移*/
      display:inline-block;
      line-height: 24px;
      font-size: 24px;
      transition: all 0.4s linear;
      opacity: 1;
      transform: translate3d(0,0,0);
      .inner{ /*文字层负责旋转*/
        display:inline-block;
        padding: 6px;
        color:#00A0DC;
        transition:all 0.4s linear;
        transform: rotate(0deg);
      }
      &.move-enter-active, &.move-leave-active {
        transition: all 0.4s linear;
      }
      &.move-enter, &.move-leave-active{
        opacity: 0;
        transform: translate3d(24px,0,0);
        .inner{
          transform: rotate(180deg);
        }
      }
    }
    .cart-count{
      display:inline-block;
      vertical-align: top;
      width:12px;
      padding-top:6px;
      line-height: 24px;
      text-align: center;
      font-size: 10px;
      color:rgb(147,153,159);
    }
    .cart-add{
      display:inline-block;
      line-height: 24px;
      font-size: 24px;
      padding: 6px;
      color:#00A0DC;
    }
  }
</style>

4 点击购物车出现列表(购物列表可折叠 增加 减少产品数量) src/components/shopcart.vue

<template>
  <div>
    <div class="shop-cart">
      <div class="content" @click="toggleList">
        <div class="con-left">
          <div class="logo-wrapper">
            <div class="logo" :class="{'highlight':totalCount>0}">
              <i class="icon-shopping_cart" :class="{'highlight':totalCount>0}"></i>
            </div>
            <div class="num" v-show="totalCount>0">{{totalCount}}</div>
          </div>
          <div class="price" :class="{'highlight':totalCount>0}">¥{{totalPrice}}</div>
          <div class="desc">另需配送费¥{{minPrice}}元</div>
        </div>
        <div class="con-right" :class="{enough:isEnoughPay}" @click.stop.prevent="pay">
          <div class="pay">{{payDesc}}</div>
        </div>
      </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>
      <transition name="fold">
        <div class="shopcart-list" v-show="listShow" transition="fold">
        <div class="list-header">
          <h2 class="title">购物车</h2>
          <span class="empty" @click="empty">清空</span>
        </div>
        <div class="list-conent" ref="listContent">
          <ul>
            <li class="food border-1px" v-for="food in selectFoods">
              <span class="name">{{food.name}}</span>
              <div class="price">
                <span>¥{{food.price*food.count}}</span>
              </div>
              <div class="cartcontroll-wrapper">
                <cart-controll @add="addFood" :food="food"></cart-controll>
              </div>
            </li>
          </ul>
        </div>
      </div>
      </transition>
    </div>
    <!--模糊背景-->
    <transition name="fade">
      <div class="list-mask" v-show="listShow" @click="hideList"></div>
    </transition>
  </div>
</template>

<script type="text/ecmascript-6">
  import cartcontroll from 'components/cartcontroll/cartcontroll';
  import BScroll from 'better-scroll';

  export default {
    data() {
      return {
        isEnoughPay: false,
        balls: [ // 小球相关
          {
            show: false
          },
          {
            show: false
          },
          {
            show: false
          },
          {
            show: false
          },
          {
            show: false
          }
        ],
        dropBalls: [], // 小球相关
        fold: false // 购物车商品详情页展开还是折叠
      };
    },
    props: { // 接收其他组件传递过来的数据
      selectFoods: {
        type: Array,
        default: []
      },
      deliveryPrice: {
        type: Number,
        default: 0
      },
      minPrice: {
        type: Number,
        default: 0
      }
    },
    computed: { // 计算
      totalPrice() { // 选中商品总价格
        let total = 0;
        this.selectFoods.forEach((food) => { // food表示selectFoods数组的每项
          total += food.price * food.count;
        });
        return total;
      },
      totalCount() { // 选中的商品总数量
        let count = 0;
        this.selectFoods.forEach((food) => { // food表示selectFoods数组的每项
          count += food.count;
        });
        return count;
      },
      payDesc() { // 判断是否满足配送条件
        if (this.totalPrice === 0) {
          this.isEnoughPay = false;
          return `¥${this.minPrice}元起送`;
        } else if (this.totalPrice < this.minPrice) {
          let diff = this.minPrice - this.totalPrice;
          this.isEnoughPay = false;
          return `还差¥${diff}元起送`;
        } else {
          this.isEnoughPay = true;
          return '去结算';
        }
      },
      listShow: function () {
        if (!this.totalCount) { // 折叠
          this.fold = true;
          return false;
        };
        let show = !this.fold; // 展开
        if (show) {
          this.$nextTick(() => {
            if (!this.scroll) { // list-show不断变化,不能变化的时候就初始化
              this.scroll = new BScroll(this.$refs.listContent, { // $refs.listContent 要和ref值一样,区分大小写
                click: true
              });
            } else {
             this.scroll.refresh();
            };
          });
        };
        return show;
      }
    },
    methods: {
      // 小球相关 开始
      drop(el) { // 取的父goods.vue组件传来的数据el
        for (let i = 0; i < this.balls.length; i++) {
          let ball = this.balls[i];
          if (!ball.show) {
            ball.show = true;
            ball.el = el;
            this.dropBalls.push(ball);
            return;
          };
        };
      },
      addFood(target) {
        console.log(1);
        this.drop(target);
      },
      beforeDrop(el) {
        let count = this.balls.length;
        while (count--) {
          let ball = this.balls[count];
          if (ball.show) {
            let rect = ball.el.getBoundingClientRect();
                  // 用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置
            let x = rect.left - 32;
            let y = -(window.innerHeight - rect.top - 22);
            // console.log(x);
            // console.log(y);
            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];
            inner.style.webkitTransform = `translate3d(${x}px,0,0)`;
            inner.style.transform = `translate3d(${x}px,0,0)`;
          }
        }
      },
      dropping(el, done) {
        /* eslint-disable no-unused-vars */
        let rf = el.offsetHeight;
        this.$nextTick(() => {
          el.style.webkitTransform = 'translate3d(0,0,0)';
          el.style.transform = 'translate3d(0,0,0)';
          let inner = el.getElementsByClassName('inner-hook')[0];
          inner.style.webkitTransform = 'translate3d(0,0,0)';
          inner.style.transform = 'translate3d(0,0,0)';
          el.addEventListener('transitionend', done);
        });
      },
      afterDrop(el) {
        let ball = this.dropBalls.shift();
        if (ball) {
          ball.show = false;
          el.style.display = 'none';
        }
      },
      // 小球相关结束
      toggleList() {
        if (!this.totalCount) {
          return;
        };
        this.fold = !this.fold;
      },
      empty() { // 清空购物车
        this.selectFoods.forEach((food) => {
          food.count = 0;
        });
      },
      hideList() { // 购物车商品列表隐藏
        this.fold = true;
      },
      pay() { // 满足支付条件点击后操作
        if (this.totalPrice < this.minPrice) {
          return;
        };
        window.alert(`支付${this.totalPrice}元`);
      }
    },
    components: {
      cartControll: cartcontroll
    }
  };
</script>

<!--<style lang="stylus" rel="stylesheet/stylus">

</style>-->
<style lang="less" rel="stylesheet/less">

  .shop-cart{
    position: fixed;
    height:48px;
    width:100%;
    left:0;
    bottom:0;
    z-index: 50;

    .content{
      display:flex;
      background-color: rgb(20,29,39);
      font-size: 0;
      .con-left{
        flex: 1;
        font-size:0px;
        .logo-wrapper,
        .price,
        .desc{
          display: inline-block;
        }
        .logo-wrapper{
          position: relative;
          top:-10px;
          margin:0 12px;
          padding: 6px;
          width:56px;
          height:56px;
          box-sizing: border-box;
          vertical-align: top;
          border-radius:50%;
          background-color:#141d27;
          .logo{
            width:100%;
            height: 100%;
            border-radius:50%;
            background-color: rgb(43,52,60);
            font-size: 24px;
            line-height: 45px;
            text-align: center;
            &.highlight{
              background:rgb(0,160,220)
            }
            .icon-shopping_cart{
              color:rgba(255,255,255,0.4);
              font-size: 24px;
              &.highlight{
                color:#fff;
              }
            }
          }
          .num{
            position: absolute;
            top:0;
            right:0;
            width:24px;
            height:16px;
            line-height: 16px;
            text-align: center;
            border-radius: 16px;
            font-size: 9px;
            font-weight: 700;
            color:#fff;
            background-color: rgb(240,20,20);
            box-shadow: 0 4px 8px 0 rgba(0,0,0,0.4);
          }
        }
        .price{
          display: inline-block;
          vertical-align: top;
          margin-top: 12px;
          line-height: 24px;
          height:24px;
          padding-right: 12px;
          box-sizing: border-box;
          border-right: 1px solid rgba(255,255,255,0.1);
          font-size: 16px;
          font-weight: 700;
          color:rgb(127,133,138);
          &.highlight{
           color:#fff;
          }
        }
        .desc{
          display: inline-block;
          font-size: 10px;
          line-height: 24px;
          height:24px;
          color:rgb(127,133,138);
          margin-top:12px;
          text-indent: 12px;
        }
      }
      .con-right{
        flex: 0 0 105px;
        width: 105px;
        line-height: 48px;
        height:48px;
        padding:0 8px;
        box-sizing: border-box;
        color:rgb(127,133,138);
        background-color: rgb(43,52,60);
        text-align: center;
        &.enough{
          background-color:#34B413;
          .pay{
            color:#fff;
            font-size: 16px;
          }
        }
        .pay{
          font-size: 12px;
          font-weight: 700;
        }
      }
    }
    .ball-container{
      .ball{
        position: fixed;
        left:32px;
        bottom:22px;
        z-index: 200;
        &.drop-transition{
          transition: all 0.4s cubic-bezier(0.49,-0.29,0.75,0.41);
          .inner{
            width:16px;
            height: 16px;
            border-radius: 50%;
            background-color: rgb(0,160,220);
            transition:all 0.4s linear;
          }
        }
      }
    }
    .shopcart-list{
      position: absolute;
      left:0;
      top:0;
      z-index: -1;
      width:100%;
      transform: translate3d(0,-100%,0);
      &.fold-enter-active, &.fold-leave-active{
        transition:all 0.5s;
      }
      &.fold-enter,&.fold-leave-active{
        transform: translate3d(0,0,0);
      }
      .list-header{
        height:40px;
        line-height: 40px;
        padding:0 18px;
        background-color: #f3f5f7;
        border-bottom:1px solid rgba(7,17,27,0.1);
        .title{
          float:left;
          font-size: 14px;
          color:rgb(7,17,27);
        }
        .empty{
          float: right;
          font-size:12px;
          color:rgb(0,160,220);
        }
      }
      .list-conent{
        padding:0 18px;
        max-height:217px;
        background-color: #fff;
        overflow:hidden;
        .food{
          position: relative;
          padding:12px 0;
          border-bottom:1px solid rgba(7,17,27,0.1);
          .name{
            line-height: 24px;
            font-size: 14px;
            color:rgb(7,17,27);
          }
          .price{
            position: absolute;
            right:94px;
            bottom:12px;
            line-height: 24px;
            font-size: 14px;
            font-weight: 700;
            color:rgb(240,20,20);
          }
          .cartcontroll-wrapper{
            position: absolute;
            right:0;
            bottom:6px;
          }
        }
      }
    }
  }
  .list-mask{
    position:fixed;
    top:0;
    left:0;
    width:100%;
    height:100%;
    z-index:40;
    backdrop-filter:blur(10px);
    opacity: 1;
    background: rgba(7, 17, 27, 0.6);
    &.fade-enter-active, &.fade-leave-active{
       transition:0.5s all;
     }
    &.fade-enter,&.fade-leave-active{
      opacity:0;
      background:rgba(7,17,27,0);
    }
  }
</style>

 

 组件间简单图解

 

posted @ 2017-04-14 00:46  Jesonhu  阅读(320)  评论(0编辑  收藏  举报
Top