vue 实现商城中选择规格后加入购物车组件(类似淘宝)
金蝶云社区-honey缘木鱼
honey缘木鱼
24人赞赏了该文章 2,330次浏览 未经作者许可,禁止转载编辑于2018年11月09日 09:33:08

最近在写一个关于商城的vue的项目,提到商城自然就会想到买东西,选择商品规格,购物车的一些需求,作为几年移动端开发经验,突然写起了前端页面,很是费劲,最终还是实现了需求,完成了功能。

一.先看下最终实现的需求页面

屏幕快照 2018-11-08 下午7.24.53.png屏幕快照 2018-11-08 下午7.25.36.png


二.看下后台返回数据格式说明

根据商品id请求所有规格,每个颜色对应的尺码,所有组合的可能性都会返回,即使库存数辆为空,也会返回这一条记录,让前端判断是否展示,后台返回结构如下图所示:

屏幕快照 2018-11-08 下午7.31.08.png

三.具体功能要求

(1).弹出此页面时,库存,价钱为默认,颜色,尺码所有可能性展示

(2). 选中颜色时,尺码中没有对应此颜色或库存没有的要置灰,不能点击,库存数量,价钱,及商品图根据选择颜色尺码做对应的改变,先选择尺码亦是如此。

(3).选中后再次弹出要为默认选中状态,点击右上角图片,可以查看放大及要有滑动功能。


四.具体实现代码逻辑

先理下思路:要求出每种颜色对应的所有尺码对象,求出每种尺码对应的所有颜色对象,要考虑到去重,及是否选中,是否有库存

for (var i = 0; i < _this.colorsAndRules.length; i++) {
  allColors.push(_this.colorsAndRules[i].color)
  allRules.push(_this.colorsAndRules[i].size)
}

// 每个颜色对应尺寸设置是否有库存的标签
var newAllRules = []
for (var i = 0; i < Array.from(new Set(allRules)).length; i++) {
  var selColor = {
    'rules': Array.from(new Set(allRules))[i],
    'isHasRule': false
  }
  newAllRules.push(selColor)
}
for (var i = 0; i < newAllRules.length; i++) {
  for (var j = 0; j < _this.colorsAndRules.length; j++) {
    if (_this.colorsAndRules[j].size === newAllRules[i].rules) {
      if (_this.colorsAndRules[j].stock > 0) {
        newAllRules[i].isHasRule = true
        break
      }
    }
  }
}

_this.allRules = minSort(newAllRules)//对尺码做了排序

所有颜色同理。

页面要展示到所有颜色,尺码:

屏幕快照 2018-11-08 下午8.08.44.png        屏幕快照 2018-11-08 下午8.06.50.png

每个颜色对应所有的尺码对象,代码如下:

var selColors = []
var selRules = []
// 获取每个颜色对应的尺寸
for (var i = 0; i < _this.allColors.length; i++) {
  var allRules = []
  for (var j = 0; j < _this.colorsAndRules.length; j++) {
    if (_this.allColors[i].color === _this.colorsAndRules[j].color) {
      allRules.push(_this.colorsAndRules[j])
    }
  }
  console.log('已选中' + _this.isSelectColor)
  var colorAndRule
  if (_this.isSelectColor != '' && _this.allColors[i].color === _this.isSelectColor) {
    colorAndRule = {
      'isSelectColor': true
    }
  } else {
    colorAndRule = {
      'isSelectColor': false
    }
  }
  var eveColor = _this.allColors[i].color
  colorAndRule[eveColor] = allRules
  selColors.push(colorAndRule)
}

每个尺码对应的颜色对象:

for (var i = 0; i < _this.allRules.length; i++) {
  var allColors = []
  for (var j = 0; j < _this.colorsAndRules.length; j++) {
    if (_this.allRules[i].rules === _this.colorsAndRules[j].size) {
      allColors.push(_this.colorsAndRules[j])
    }
  }
  var eveRule = _this.allRules[i].rules
  var colorAndRule
  if (_this.isSelectRule != '' && _this.allRules[i].rules === _this.isSelectRule) {
    colorAndRule = {
      'isSelectRule': true
    }
  } else {
    colorAndRule = {
      'isSelectRule': false
    }
  }
  colorAndRule[eveRule] = allColors
  selRules.push(colorAndRule)
}
_this.selectRules = selRules


屏幕快照 2018-11-08 下午8.13.24.png屏幕快照 2018-11-08 下午8.12.07.png


点击选中颜色代码:

// 点击选中颜色
isSelectCol (index, color) {
  var _this = this
  var hasRules = []
  for (var i = 0; i < _this.selectColors.length; i++) {
    if (index === i) {
      _this.selectColors[i].isSelectColor = true
      for (var key in _this.selectColors[i]) {
        if (key === color) {
          hasRules = _this.selectColors[i][key]
          _this.isSelectColor = color
        }
      }
    } else {
      _this.selectColors[i].isSelectColor = false
    }
  }
  // 所有尺寸全为空
  for (var j = 0; j < _this.allRules.length; j++) {
    _this.allRules[j].isHasRule = false
  }
  // 库存中存在的致为可选
  for (var i = 0; i < hasRules.length; i++) {
    for (var j = 0; j < _this.allRules.length; j++) {
      if (_this.allRules[j].rules === hasRules[i].size && hasRules[i].stock > 0) {
        _this.allRules[j].isHasRule = true
      }
    }
    if (_this.isSelectRule !== '') {
      if (hasRules[i].size === _this.isSelectRule) {
        _this.selectedGoods = hasRules[i]
        _this.imgUrls = hasRules[i].pictures
      }
    }
  }
  if (_this.isSelectRule === '') {
    _this.expressSelected = '请选择尺码'
  } else {
    _this.expressSelected = '已选' + ' ' + _this.isSelectColor + ' 尺码' + _this.isSelectRule
  }
},

选中尺码同理


页面布局的实现:

<div class="selectGoods">
    <div class="selColor">
      <div class="selected">颜色分类</div>
      <div v-for="(item,index) in selectColors" :key="index"  class="selColor">
        <div class="colorSel"  @click="isSelectCol(index,allColors[index].color)" v-if="allColors[index].isHasColor&&!item.isSelectColor">{{allColors[index].color}}</div>
        <div class="selectedColor" v-else-if="allColors[index].isHasColor&&item.isSelectColor" >{{allColors[index].color}}</div>
        <div class="noColorRules" v-else >{{allColors[index].color}}</div>
      </div>
    </div>
    <div class="selRules">
      <div class="selected">选择尺码</div>
      <div v-for="(item,index) in selectRules" :key="index" class="selColor">
        <div class="colorRules" @click="isSelectSize(index,allRules[index].rules)" v-if="allRules[index].isHasRule&&!item.isSelectRule">{{allRules[index].rules}}</div>
        <div class="selectedColor"  v-else-if="allRules[index].isHasRule&&item.isSelectRule">{{allRules[index].rules}}</div>
        <!--<div class="noColorRules"  v-if="!allRules[index].isHasRule">{{allRules[index].rules}}</div>-->
        <div class="noColorRules" v-else >{{allRules[index].rules}}</div>
      </div>
    </div>
  </div>


点击放大图的实现原理为,引用的mint-ui中轮播图的理念,因为前端手势比较麻烦,就用了非自动的录播图实现具体代码为:

 <!--图片放大功能-->
<div class="imgMask" v-if="showBigImg" @click.stop="showBigImg=!showBigImg">
  <div class="showImg">
    <mt-swipe :auto="0" :show-indicators="false" :continuous="false" :defaultIndex="num">
      <mt-swipe-item v-for="(item,index) in imgUrls" :key="item.id">
        <div class="testNum"  >{{index+1+'/'+imgUrls.length}}</div>
        <img :src=" $headerImg+imgUrls[index]+$bigImg" class="img"/>
      </mt-swipe-item>
    </mt-swipe>
  </div>


我已把这块写为组件,需要源码的及不懂的地方请评论联系!写的不对的地方,请指出,并请多多包含前端小白!


     本文独发金蝶云社区。

赞 24