小程序-仿小米有品商城

前言

做爲一個剛入門學前端的小白我來講,寫這個小程序花了不少時間,遇到了不少問題,也學到了不少,很是感謝那些幫我解決問題的老師和同窗。這個小程序主要實現的是購物車功能,有些許功能未得以實現,好比搜索功能,因爲小米有品沒有開源的api,搜索的不少數據須要本身來寫,以爲這是一項巨大的工程,而後你懂得(就沒寫搜索功能了)。項目地址。但願能給初學者一些幫助。前端

開發前的準備

項目部分截圖(gif)

項目主要頁面及功能實現

首頁

  • 商品詳情頁功能實現

1.分享功能 利用button組件,把catchtap="shares"來點擊分享實現分享給微信好友的彈框(同時出現遮罩層),在此以前要先給包容彈框的盒子設置一個遮罩層,點擊頁面的任何一個地方遮罩層消失。 git

<view class="share-mask {{active ? 'active' : ''}}" bindtap="hideMask">
  <view class="shares">  
      <view class="share">分享</view>
      <view class="share_content">
        <view class="share_left">
          <button catchtap="shares" class="shares-btn" open-type="share" hover-class="none">
            <image class="shareImg" src="../../../images/wechat.png"/>
            <text>發送給朋友</text>
          </button>
        </view>    
        <view class="share_right">
          <image class="shareImg" src="../../../images/poster.png"/>
          <text>生成圖庫</text>
        </view>
      </view>
      <view class="cancel">取消</view>
  </view>
</view>

複製代碼
// 分享
  toShare() {
    this.setData({
      active: true
    })
  },
  // 隱藏遮罩層
  hideMask() {
    this.setData({
      active: false
    })
  },
  // 分享給微信好友
  onShareAppMessage (options) {
    return {
      title:this.data.detail[0].detailOne
    }
  }
複製代碼

分類頁面

request請求並獲取數據,點擊商品分類跳轉相關商品集合

<view class="category-left">
        <view wx:for="{{category}}" wx:key="{{item.id}}"
         data-id="{{item.id}}" data-index="{{index}}"
         class="cate-list {{ curIndex === index ? 'on' : '' }}" bindtap="switchTab" >{{item.name}}</view>
    </view>
    <scroll-view class="categroy-right" scroll-y scroll-into-view="{{toView}}" scroll-with-animation="{{true}}">
            <view class="cate-box" id="{{detailList.id}}">
                <view class="cate-banner">
                    <image src="{{detailList.banner}}"></image>
                </view>
                <view class="cate-title">
                    <text>{{detailList.cate}}</text>
                </view>
                <view class="product">
                    <view class="product-list" wx:for="{{detailList.detail}}" wx:key="index" wx:for-item="product">
                        <navigator url="#">
                            <image src="{{product.thumb}}" />
                            <view class="classname">
                                <text>{{product.name}}</text>
                            </view>
                        </navigator>
                    </view>
                </view>
            </view>
    </scroll-view>
複製代碼
Page({
  data: {
    category:[],
      detail: [],
    detailList: {},
    curIndex:0,
    toView:"youpin",
  },
  switchTab(e){
    let currentId = e.currentTarget.dataset.id
    let currentIndex = e.currentTarget.dataset.index
    this.setData({
      detailList: this.data.detail[currentIndex],
      curIndex: currentIndex
    })
  }
複製代碼

購物車頁面

此頁面簡單的實現了點擊首頁的商品,購物車會顯示相關加入的商品,以及加減、全選、取消全選(點擊任意一個商品,全選消失)的功能。es6

selectAll() {
    let selectAllStatus = this.data.selectAllStatus
    selectAllStatus = !selectAllStatus
    let carts = this.data.carts
    for (let i = 0; i < carts.length; i++) {
      carts[i].selected = selectAllStatus
    }
    this.setData({
      selectAllStatus,
      carts
    })
    this.getTotalPrice()
  },
  selectList (e) {
    console.log(e.currentTarget.dataset.index)
    let oIndex = e.currentTarget.dataset.index
    let carts = this.data.carts
    let test = carts[oIndex].selected
    test = !test
    let cartSelect = `carts[${oIndex}].selected`
    this.setData({
      [cartSelect]: test
    })
    if (this.data.carts.find(function(e) {return e.selected === false})) {
      this.setData({
        selectAllStatus: false
      })
    } else {
      this.setData({
        selectAllStatus: true
      })
    }
    this.getTotalPrice()
  },
  getTotalPrice() {
    let carts = this.data.carts
    let total = 0
    let totalNum = 0
    for (let i = 0; i < carts.length; i++) {
      if (carts[i].selected) {
        total += carts[i].num * carts[i].price
        totalNum += carts[i].num
      }
    }
    this.setData({
      totalPrice: total.toFixed(2),
      totalNum
    })
  },
  minusCount(e) {
    // console.log(e)
    const index = e.target.id
    let carts = this.data.carts
    // console.log(index,carts)
    let num = carts[index].num
    if (num <= 1) {
      return
    }
    num = num - 1
    carts[index].num = num
    this.setData({
      carts: carts
    })
    this.getTotalPrice()
  },
  addCount(e) {
    const index = e.target.id
    let carts = this.data.carts
    let num = carts[index].num
    num = num + 1
    carts[index].num = num
    this.setData({
      carts: carts
    })
    this.getTotalPrice()
  },
複製代碼

我的頁面

該頁面沒怎麼寫功能,大部分都是靜態的,就不過多介紹了。github

頁面傳值

使用全局變量解決頁面的傳值問題

主要是點擊商品詳情頁(goods.js)的加入購物車,購物車頁面(cart.js)會顯示被加入的商品,經過把數據存儲在全局變量裏來傳值。小程序

1.首先在app.js全局變量裏定義一個carts[]數組 globalData: { cart:[] }api

2.其次在goods.js頁面和cart.js頁面頭部定義const app = getApp(); 在goods.js的addCart()方法裏app.globalData.cart = [...app.globalData.cart, this.data.detail] 用es6的解構方法,把從easy-mock裏獲取到的detail[]傳到全局變量的cart[]裏。這種寫法與push()方法不一樣在於push()方法會修改數組裏的值,而不是建立一個新的數組。數組

3.最後在cart.js的onShow生命週期裏設置購物車的數據源,即獲取goods.js在app.js裏的cart[]緩存

this.setData({
        hasGoods: true,
        carts: app.globalData.cart
      })
複製代碼

點擊首頁的商品列表跳到相應的商品詳情頁

首頁跳轉到商品詳情頁時,經過每一個商品的id來跳轉bash

// pages/index/index.js
// 去到商品詳情頁
  toLists:function(e) {
    // console.log(e)
    let id = e.currentTarget.dataset.id
    wx.navigateTo({
      url: `/pages/goods/goods/goods?id=${id}`
    })
  }
複製代碼

在商品詳情頁把商品的id賦值給商品的index來設置數據源微信

// pages/goods/goods.js
 onLoad: function (options) {
    const id = options.id
    this.setData({
      index: id
    })
  }
複製代碼

使用路徑傳參

如:/pages/goods/goods/goods?id=${id} ,這裏應注意下,若是參數要傳的值是一條對象的話,咱們都知道小程序裏是不支持傳對象的,此時把值傳過去的時候應該用JSON.stringify()把對象轉爲字符串,拿到值的時候應該用JSON.parse()把字符串轉爲對象。

頁面其它功能

商品結算時的合計

onShow () {
    let self = this
    wx.request({
      url:'https://www.easy-mock.com/mock/5d077b333780f05f8385d2c1/xiaoMi_youPin/goods_detail',
      success(res){
        console.log(res)
        self.setData({
          goods:res.data.data.goods
        })
        self.setData({
          sum: self.data.goods[0].goodsPrice + self.data.goods[0].carriage - self.data.goods[0].discounts
        })
      }
    })
  }
複製代碼

這裏的合計是寫在onShow聲明週期裏的,我想說的是應該注意計算合計與請求接口數據會產生異步問題, 應該把計算合計另外放在self.setData({})裏,並放在請求接口數據的self.setData({})下面,由於請求接口數據的時間大於計算合計的時間,必需要拿到數據後才能計算合計。這兩個不能放在同一個self.setData({})裏,不然得不到合計的值,以下代碼是不正確的

self.setData({
          goods:res.data.data.goods,
          sum: self.data.goods[0].goodsPrice + self.data.goods[0].carriage - self.data.goods[0].discounts
        })
複製代碼

收穫地址管理

用戶收穫地址管理實現了新增地址和管理地址功能,在utils文件夾下引入了weui.wxss和自定義了身份城市區縣的數據area.js。

//pages/goods/addressList/addressList.js
Page({
  data: {
    addressList:[]
  },
  onLoad: function (options) {
    var arr = wx.getStorageSync('addressList') || [];
    console.info("緩存數據:" + arr);
    // 更新數據  
    this.setData({
      addressList: arr
    });
  },
  onShow: function () {
    this.onLoad();
  },
  addAddress:function(){
    wx.navigateTo({ 
      url: '../../goods/address/address' 
    });
  },
  /* 刪除item */
  delAddress: function (e) {
    this.data.addressList.splice(e.target.id.substring(3), 1);
    // 更新data數據對象  
    if (this.data.addressList.length > 0) {
      this.setData({
        addressList: this.data.addressList
      })
      wx.setStorageSync('addressList', this.data.addressList);
    } else {
      this.setData({
        addressList: this.data.addressList
      })
      wx.setStorageSync('addressList', []);
    }
  }
})
複製代碼
//pages/goods/address/address.js
var area = require('../../../utils/area.js');
var areaInfo = []; //全部省市區縣數據
var provinces = []; //省
var provinceNames = []; //省名稱
var citys = []; //城市
var cityNames = []; //城市名稱
var countys = []; //區縣
var countyNames = []; //區縣名稱
var value = [0, 0, 0]; //數據位置下標
var addressList = null;
Page({
  data: {
    transportValues: ["收貨時間不限", "週六日/節假日收貨", "週一至週五收貨"],
    transportIndex: 0,
    provinceIndex: 0, //省份
    cityIndex: 0, //城市
    countyIndex: 0, //區縣
    provinceNames: ["江西省","北京省"]
  },
  onShow: function() {
    var that = this;
    area.getAreaInfo(function(arr) {
      areaInfo = arr;
      //獲取省份數據
      that.getProvinceData();
    });
  },
  // 獲取省份數據
  getProvinceData: function() {
    var that = this;
    var s;
    provinces = [];
    provinceNames = [];
    var num = 0;
    for (var i = 0; i < areaInfo.length; i++) {
      s = areaInfo[i];
      if (s.di == "00" && s.xian == "00") {
        provinces[num] = s;
        provinceNames[num] = s.name;
        num++;
      }
    }
    that.setData({
      provinceNames: provinceNames
    })

    that.getCityArr();
    that.getCountyInfo();
  },

  // 獲取城市數據
  getCityArr: function(count = 0) {
    var c;
    citys = [];
    cityNames = [];
    var num = 0;
    for (var i = 0; i < areaInfo.length; i++) {
      c = areaInfo[i];
      if (c.xian == "00" && c.sheng == provinces[count].sheng && c.di != "00") {
        citys[num] = c;
        cityNames[num] = c.name;
        num++;
      }
    }
    if (citys.length == 0) {
      citys[0] = {
        name: ''
      };
      cityNames[0] = {
        name: ''
      };
    }
    var that = this;
    that.setData({
      citys: citys,
      cityNames: cityNames
    })
    console.log('cityNames:' + cityNames);
    that.getCountyInfo(count, 0);
  },

  // 獲取區縣數據
  getCountyInfo: function(column0 = 0, column1 = 0) {
    var c;
    countys = [];
    countyNames = [];
    var num = 0;
    for (var i = 0; i < areaInfo.length; i++) {
      c = areaInfo[i];
      if (c.xian != "00" && c.sheng == provinces[column0].sheng && c.di == citys[column1].di) {
        countys[num] = c;
        countyNames[num] = c.name;
        num++;
      }
    }
    if (countys.length == 0) {
      countys[0] = {
        name: ''
      };
      countyNames[0] = {
        name: ''
      };
    }
    console.log('countyNames:' + countyNames);
    var that = this;
    that.setData({
      countys: countys,
      countyNames: countyNames
    })
  },

  bindTransportDayChange: function(e) {
    console.log('picker country 發生選擇改變,攜帶值爲', e.detail.value);
    this.setData({
      transportIndex: e.detail.value
    })
  },

  bindProvinceNameChange: function(e) {
    var that = this;
    console.log('picker province 發生選擇改變,攜帶值爲', e.detail.value);
    var val = e.detail.value
    that.getCityArr(val); //獲取地級市數據
    that.getCountyInfo(val, 0); //獲取區縣數據

    value = [val, 0, 0];
    this.setData({
      provinceIndex: e.detail.value,
      cityIndex: 0,
      countyIndex: 0,
      value: value
    })
  },

  bindCityNameChange: function(e) {
    var that = this;
    console.log('picker city 發生選擇改變,攜帶值爲', e.detail.value);
    var val = e.detail.value
    that.getCountyInfo(value[0], val); //獲取區縣數據
    value = [value[0], val, 0];
    this.setData({
      cityIndex: e.detail.value,
      countyIndex: 0,
      value: value
    })
  },

  bindCountyNameChange: function(e) {
    var that = this;
    console.log('picker county 發生選擇改變,攜帶值爲', e.detail.value);
    this.setData({
      countyIndex: e.detail.value
    })
  },

  saveAddress: function(e) {
    var consignee = e.detail.value.consignee;
    var mobile = e.detail.value.mobile;
    var transportDay = e.detail.value.transportDay;
    var provinceName = e.detail.value.provinceName;
    var cityName = e.detail.value.cityName;
    var countyName = e.detail.value.countyName;
    var address = e.detail.value.address;
    console.log(transportDay + "," + provinceName + "," + cityName + "," + countyName + "," + address); //輸出該文本 
    var arr = wx.getStorageSync('addressList') || [];
    console.log("arr,{}", arr);
    addressList = {
      consignee: consignee,
      mobile: mobile,
      address: provinceName + cityName + countyName+address,
      transportDay: transportDay
    }
      arr.push(addressList);
    wx.setStorageSync('addressList', arr);
    wx.navigateBack({ })
  }
})
複製代碼

結語

這個小程序做爲我學前端以來寫的第一個項目,寫的過程是漫長的,同時也是痛並快樂着的。但願能給那些初寫小程序商城的同窗們一些幫助,畢竟我剛開始寫這個小程序的時候是迷茫的,不知如何下手。以爲寫得還ok的話,可不能夠動動大家的小拇指給我點個贊呢!如有哪寫得不足得地方能夠在下面的評論區附上大家的建議。最後再加一句,我是2020屆的畢業生,即將面臨實習的壓力,有哪位大佬能夠稍微關照下嘛。

相關文章
相關標籤/搜索