小程序购物车项目应用

小程序项目


app.json文件
“pages”小程序页面路径
“window”设置项目头部
“tabBar”设置底部菜单切换

{
  "pages": [
    "pages/index/index",
    "pages/list/list",
    "pages/food/food",
    "pages/myCart/myCart",
    "pages/indexDetail/indexDetail"
  ],
  "window": {
    "backgroundColor": "#F6F6F6",
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#43bf92",
    "navigationBarTitleText": "安心食疗",
    //字体颜色
    "navigationBarTextStyle": "white" 
  },
  "tabBar": {
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "images/home.png",
        "selectedIconPath": "images/home-active.png"
      },
      {
        "pagePath": "pages/food/food",
        "text": "食物分类",
        "iconPath": "images/cate.png",
        "selectedIconPath": "images/cate-active.png"
      },
      {
        "pagePath": "pages/myCart/myCart",
        "text": "购物车",
        "iconPath": "images/cart.png",
        "selectedIconPath": "images/cart-active.png"
      },
      {
        "pagePath": "pages/list/list",
        "text": "我的",
        "iconPath": "images/my.png",
        "selectedIconPath": "images/my-active.png"
      }
    ]
  },
  "sitemapLocation": "sitemap.json",
  "style": "v2"
}

首页

1.页面制作
在这里插入图片描述
index.wxml

<!-- 轮播图 -->
<view class="banner">
  <swiper autoplay="true" interval="3000" bindchange="swiperChange">
    <swiper-item wx:for="{{bannerArr}}" wx:key="index">
      <navigator url="{{item.url}}">
        <image src="{{item.image}}"></image>
        <view class="desc">{{item.title}}</view>
      </navigator>
    </swiper-item>
  </swiper>
  <!-- 当前页码 -->
  <view class="banner-current">{{currentIndex+1}}/{{bannerArr.length}}</view>
</view>
<!-- 每日一测 -->
<view class="one-day">
  <view class="one-item">
    <image src="../../images/bacg1.jpg"></image>
    <view>每日一测</view>
  </view>
  <view class="one-item">
    <image src="../../images/bacg2.jpg"></image>
    <view>每日一测</view>
  </view>
</view>
<!-- list-->
<view class="home-list">
  <view class="home-item" wx:for="{{list}}" wx:key="{{index}}">
      <view>{{item.title}}</view>
      <view class="home-con">
        <view>
          <image src="{{item.image}}" />
        </view>
        <view class="home-text">
          <view class="home-text-top">{{item.desc}}</view>
          <view style="display: flex;justify-content: flex-end;">
            <view style="color: red;">{{item.readNum}}</view>次阅读
          </view>
        </view>
      </view>
  </view>
</view>

index.js文件

// pages/food/food.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    currentIndex:0,
    bannerArr:[],
    list:[]

  },
  // 轮播图自动播放修改时触发
  swiperChange:function(e){
    this.setData({currentIndex:e.detail.current})
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    // 进入页面请求轮播数据
    wx.showLoading({
      title: '数据加载中',
    })
    var that=this;
    wx.request({
     
      url: 'http://iwenwiki.com:3002/api/banner',
      success:function(res){
        if(res.data.status==200){
          that.setData({bannerArr:res.data.data})
        }
        
      }
    }),
    // 请求列表数据
    wx.request({
      url: 'http://iwenwiki.com:3002/api/indexlist',
      success:function(res){
        if(res.data.status==200){
          that.setData({list:res.data.data})
        } 
      },
      complete:function(){
        wx.hideLoading()
      }
    })

  },
})

index.wxss

<style>
.banner swiper{
  height: 338rpx;
  width: 100%;
}
.banner{
  position: relative;
  height: 338rpx;
}
.banner image{
  width: 100%;
  height: 338rpx;
}
.banner .swiper-item{
  position: relative;
}
.banner .desc{
  position: absolute;
  background-color: rgb(0,0,0,0.5);
  color: #ffffff;
  left: 0;
  bottom: 0;
  right: 0;
  padding: 10rpx;
  font-size: 24rpx;
  text-align: center;

}
.banner .banner-current{
  position: absolute;
  right: 20rpx;
  bottom: 18rpx;
  color: #ffffff;
  font-size: 20rpx;
}
 .one-day{
  margin: 34rpx 0;
  display: flex;
  padding: 0 20rpx;
  justify-content: space-around;
}
.one-item image{
  width: 306rpx;
  height: 185rpx;
  border-radius: 5rpx;
}
.one-item view{
  text-align: center;
  font-size: 28rpx;
  color: #999;
}
.home-list{
  margin-top: 20rpx;
}
.home-item{
  padding: 15rpx;
  border-bottom: 1px solid #cccccc;
}
.home-con{
  display: flex;
  margin-top: 5rpx;
}
.home-con image{
  width: 280rpx;
  height: 150rpx;
  border-radius: 5rpx;
}
.home-text{
  margin-left: 5rpx;
  font-size: 24rpx;
  color: #999999;
}
.home-text-top{
  height: 125rpx;
}
</style>

2.点击列表跳转至详情页面
先新建详情页面,后跳转传参

  • 首页跳转至详情页面方法
    小程序传参第一种,通过组件,在对应的跳转页面js文件里面通过onload函数options来接收
    第二种传参 利用事件 bindtap='indexDetail’点击是哪个元素 事件传参data-属性=‘属性值’ 事件wx.api跳转,在对应的跳转页面js文件里面通过onload函数options来接收
<view class="home-list">
  <view class="home-item" wx:for="{{list}}" wx:key="{{index}}" bindtap='indexDetail' data-id='{{item.id}}'>
  <!-- 小程序传参第一种,通过<navigator></navigator>组件,在对应的跳转页面js文件里面通过onload函数options来接收 -->
  <!-- 第二种传参 利用事件 bindtap='indexDetail'点击是哪个元素 事件传参data-属性='属性值' 事件wx.api跳转-->
    <!-- <navigator url="../indexDetail/indexDetail?itemId={{item.id}}"> -->
      <view>{{item.title}}</view>
      <view class="home-con">
        <view>
          <image src="{{item.image}}" />
        </view>
        <view class="home-text">
          <view class="home-text-top">{{item.desc}}</view>
          <view style="display: flex;justify-content: flex-end;">
            <view style="color: red;">{{item.readNum}}</view>次阅读
          </view>
        </view>
      </view>
    <!-- </navigator> -->
  </view>
</view>

通过绑定事件传参在index.js页面中

 //页面列表跳转
  indexDetail:function(e){
    // 获取当前点击元素的值
    console.log(e.currentTarget.dataset.id)
    // 跳转页面
    wx.navigateTo({
      url: '../indexDetail/indexDetail?itemId='+e.currentTarget.dataset.id,
    })
    //接收还是options
  },
  • 详情页面
    页面
<!-- 标题 -->
<view class="title">{{indexDetail.title}}</view>
<!-- 图片 -->
<image class="img" src="{{indexDetail.image}}"></image>
<!-- 文章 -->
<view class="article">{{indexDetail.detail}}</view>

indexDetail.js接收首页传参
通过 wx.setNavigationBarTitle方法动态改变nav的值

// pages/indexDetail/indexDetail.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    indexDetail:''
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    // options接收其他页面跳转进入这个页面传递的url参数
    wx.showLoading({
      title: '数据加载中',
    })
    wx.showNavigationBarLoading()
    //请求详情数据
    wx.request({
      url: 'http://iwenwiki.com:3002/api/indexlist/detail',
      data:{
        id:options.itemId
      },success:res=>{
        this.setData({indexDetail:res.data[0]})
        //NavigationBar名称,动态
        wx.setNavigationBarTitle({
          title: res.data[0].title,
        })
      },
      complete:function(){
        wx.hideLoading()
        wx.hideNavigationBarLoading()
      }
    })
  },
})

indexDetail.wxss

<style>
.title{
  margin: 20rpx;
  font-size: 36rpx;
}
.img{
  width: 100%;
  height: 400rpx;
  margin-bottom: 20rpx;
}
.article{
  padding: 20rpx;
  text-align: justify;
  color: #888;
  font-size: 30rpx;
  line-height: 40rpx;
  text-indent: 2em;
}
</style>

3.为了方便使用还可以对接口做封装
与app.js同级建http.js文件
网络请求封装方法
参数1:method 请求方式 get/post(string) 请求类型
参数2:url(string)请求的url地址
参数3:params(json)请求携带参数
参数4:message(string) loading 信息弹框信息
参数5:success 成功函数
参数6:fail失败函数

function http(method,url,params,message,success,fail){
  if(message!=''){
    wx.showLoading({
      title: message,
    })
  }
  //请求
  wx.request({
    // 写一个请求域名 后期修改域名网站 统一修改
    url: 'http://iwenwiki.com:3002'+url,
    method:method,
    data:params,
    success:res=>{
      if(res.data.status==200){
        success(res.data)
      }else{
        fail(res.data);
      }
    },
    fail:function(res){
      fail(res.data);
    },
    complete:function(res){
      if(message!=''){
        wx.hideLoading()
      }
    }
  })
}

//暴露出去
module.exports=http;

分类

在这里插入图片描述
页面包括分类首页、定位、搜索页面
1.首页.wxml页面,因为商品列表用的比较多所以把它封装成一个模板

  • 模板定义和使用 :
    1.创建模板文件 定义模板(只包含wxml,wxss)
    2.定义模板 wxml:
    3.引入模板
    4.使用模板

    5.使用模板样式,对应引入wxss @import ‘wxss路径’
  • 模板传值


    …展开运算符
    item={id:‘’,pic:‘’…},获取名字item.name
    …item 展开对象{} 获取对象name
<!-- 搜索框 -->
<view class="header">
<!-- 1.点击选择城市--跳转页面 跳转对应的页面 请求热门城市
 2.渲染城市
 3.定位--获取经纬度(选择城市)
 4.选择城市后返回食疗方页面-->
  <view class="location">
    <navigator url='../selectCity/selectCity' hover-class='none'>{{location}}</navigator>
  </view>
  <view class="search">
    <navigator url='../search/search' hover-class='none'>请输入你想要的内容</navigator>
  </view>
</view>
<!-- 产品分类 -->
<view class="product-type">
  <view class="item" wx:for="{{produectType}}" wx:key="index" bindtap="productType" data-mark="{{item.id}}">
    <image src="{{item.imgUrl}}"></image>
    <view>{{item.name}}</view>
  </view>
</view>
<!-- list -->
<!-- 模板的定义和使用 -->
<!-- 为什么使用模板:当前代码片段重复使用,哪里使用哪里调用
模板定义和使用 :
1.创建模板文件 定义模板(只包含wxml,wxss)
2.定义模板 wxml:<template name=''></template>
3.引入模板 <import src='模板相对路径' />
4.使用模板 <template is='使用模板名字' />
<template is='使用模板名字'></template>
5.使用模板样式,对应引入wxss   @import 'wxss路径'-->

<!-- 模板传值 
<template is='使用模板名字' data='{{变量}}' />
<template is='使用模板名字' data='{{...变量}}' />
...展开运算符
item={id:'',pic:''...},获取名字item.name
...item 展开对象{} 获取对象name
-->
<import src='../../templates/foodList/foodList.wxml' />
<view wx:for="{{list}}" wx:key="index" bindtap="productDetail" data-id="{{item.id}}">
  <template is='foodList' data='{{item}}'/>
</view>
<!-- //点击加载更多
<button bindtap="more" wx:if="isShow">点击加载更多</button> -->
<!-- 下拉加载更多 
不需要自己判断下拉到页面底部 事件函数下拉底部函数-->

<view>{{moreInfo}}</view>

.js文件
注意:onLoad只执行一次,下一次进入页面走onShow函数

// pages/food/food.js
//引入模块
var produectType=require('../../productType')
var http=require('../../http')
var app=getApp()
Page({

  /**
   * 页面的初始数据
   */
  data: {
    location:"北京",
    produectType:produectType,
    list:[],
    num:1,
    isShow:false,
    moreInfo:""
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    //进入页面先获取本地存储 查看是否有之前选择的城市,如果有重新设置 ,没有使用默认
    var cityName=wx.getStorageSync('cityName')
    if(cityName){
      this.setData({location:cityName})
    }
    wx.request({
      url: 'http://iwenwiki.com:3002/api/foods/list',
      data:{
        city:this.data.location,
        page:this.data.num
      },success:res=>{
        if(res.data.status==200){
          this.setData({
            list:this.data.list.concat(res.data.data.result),
            isShow:true
          })
        }else{
          this.setData({
            moreInfo:"我是底线",
            isShow:false
          })
          if(res.data.msg=="暂无数据"){
            this.setData({
              moreInfo:"我是底线",
              list:[],
              isShow:false
            })}
        }
      }
    })

  },
  //产品分类--进入详情页面
  productType:function(e){
    wx.navigateTo({
      url: '../productType/productType?itemId='+e.currentTarget.dataset.mark,
    })
  },
  //进入列表详情
  productDetail:function (e) {
    wx.navigateTo({
      url: '../productDetail/productDetail?itemId='+e.currentTarget.dataset.id,
    })
  },
  //下拉底部,请求数据
  more:function(){
    //点击按钮请求下一页num++,请求完毕老数据拼接新数据
    this.data.num++
    wx.request({
      url: 'http://iwenwiki.com:3002/api/foods/list',
      data:{
        city:this.data.location,
        page:this.data.num
      },success:res=>{
        console.log(res.data.result)
        if(res.data.status==200){
          this.setData({
            list:this.data.list.concat(res.data.data.result),
            isShow:true
          })
        }else{
          //加载按钮隐藏
          this.setData({
            moreInfo:"我是底线",
            isShow:false
          })
        }
      }
    })

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
    if(app.globalData.cityName){
      this.setData({
        location:app.globalData.cityName,
        num:1
      })
      //onLoad只执行一次,下一次进入页面走onShow函数
      wx.request({
        url: 'http://iwenwiki.com:3002/api/foods/list',
        data:{
          city:app.globalData.cityName,
          page:this.data.num
        },success:res=>{
          if(res.data.status==200){
            this.setData({
              list:res.data.data.result,
              isShow:true
            })
          }else{
            this.setData({
              moreInfo:"我是底线",
              isShow:false
            })
            if(res.data.msg=="暂无数据"){
              this.setData({
                moreInfo:"我是底线",
                list:[],
                isShow:false
              })
            }
          }
        }
      })
    }
    
  },


  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {
    //请求第一页的数据,把当前新数据替换list数据,num=1
    console.log(http)


  },
  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {
    // 1.下拉加载数据下一页num++ 2.老数据+新数据
    this.data.num++;
    wx.request({
      url: 'http://iwenwiki.com:3002/api/foods/list',
      data:{
        city:this.data.location,
        page:this.data.num
      },success:res=>{
        if(res.data.status==200){
          this.setData({
            list:this.data.list.concat(res.data.data.result),
            isShow:true
          })
        }else{
          //加载按钮隐藏
          this.setData({
            moreInfo:"我是底线",
            isShow:false
          })
        }
      }
    })


  },
})
<style>
/* 引入模板样式 */
@import '../../templates/foodList/foodList.wxss';
page{
  background: #f1f1f1;
}
.header{
  display: flex;
  padding: 10rpx;
  background: #fff;
}
.location{
  width: 100rpx;
  text-align: center;
}
.search{
  background: #f1f1f1;
  color: #acacac;
  flex: 1;
  font-size: 28rpx;
  padding: 10rpx;
  border-radius: 10rpx;
}
.product-type{
  background: #ffff;
  padding-top: 20rpx;
  display: flex;
  flex-wrap: wrap;
}
.item{
  width: 25%;
  text-align: center;
  font-size: 26rpx;
  color: #666;
  margin-bottom: 20rpx;
}
.item image{
  width: 74rpx;
  height: 74rpx;
}

</style>

2.封装模板页面
与pages平级建templates文件夹如图,模板要用template标签包裹
在这里插入图片描述

<template name="foodList">
  <view class="list">
  <view class="list-img">
    <image src="{{item.pic}}"></image>
  </view>
  <view class="list-info">
    <view class="title">{{item.name}}</view>
    <view class="info">{{item.description}}</view>
    <view class="info-bottom">
      <view class="price">¥{{item.price}}</view>
      <view class="num">{{item.buynum}}人付款</view>
    </view>
  </view>
</view>
</template>
<style>
/* /* //列表样式 */
.list{
  background: #fff;
  padding: 20rpx;
  display: flex;
  margin-top: 20rpx;
}
.list-img {
 width: 184rpx;
 height: 184rpx;
}
.list-img image{
 width: 184rpx;
 height: 184rpx;
}
.list-info{
padding-left: 20rpx;
position: relative;
flex: 1;
}
.title{
 color: #333;
 font-size: 30rpx;
 margin-bottom: 14rpx;
}
.info{
 font-size: 28rpx;
 color: #666;
}
.info-bottom{
 position: absolute;
 bottom: 0rpx;
 right: 0;
 left: 20rpx;
 font-size: 24rpx;
 display: flex;
}
.price{
 color: red;
 margin-right: 30rpx;
}
.num{
 color: #333;
}
</style>

3.定位按钮
在这里插入图片描述
会跳转到定位所对应页面
.wxml

<!-- 定位 -->
<view>
当前所在城市
</view>
<button type="success" style="margin: 0;width: 90px;"  class="location" bindtap="getLocation">定位</button>
<view class="hot">热门城市</view>
<view class="city">
  <button wx:for="{{hotCity}}" bindtap="selectCity" data-name="{{item}}" style="margin: 0;padding:10px;width: 40px;font-size: 24rpx;background-color: #f1f1f1;margin-right: 10px;margin-top: 10px;font-weight: 400;" wx:key="index" >{{item}}</button> 
</view>
<map  longitude="{{longitude}}" latitude="{{latitude}}" scale="14"></map>

.wxss

<style>
page{
  padding: 20rpx;
}
.location{
  color: green;
  margin-top: 20rpx;
  margin-bottom: 20rpx;
  font-size: 30rpx;
  background-color: #f1f1f1;
}
.city{
  display: flex;
  flex-wrap: wrap;
}
</style>

.js 这里需要注意的就是

  • 传值,要把定位出来的城市传到首页(上一页)
    wx.navigateTo({}) 不能跳转
    wx.switchTab({
    url: ‘…/food/food’,
    })
    wx.navigateBack({})这两种方法返回时都不能带传参,所以用全局数据方式
    方法一:传给全局变量 ,再用 wx.switchTab
    在app.js中的globalData定义一个变量
    this.globalData = {
    cityName:“”//切换城市变量
    };
    方法二:wx.reLaunch({}),其他跳转是显示隐藏,这个是把其他的关闭,这个页面重新打开(不推荐)
  • 定位:在app.json文件中设置允许访问
    “permission”: {
    “scope.userLocation”: {
    “desc”: “小程序将获取你的定位”
    }
    },
    • 为保证刷新跳转页面后还保留原来的定位信息,可以 wx.setStorageSync(‘cityName’, cityName)存到本地
// pages/selectCity/selectCity.js
var http = require('../../http')
var app=getApp()
Page({

  /**
   * 页面的初始数据
   */
  data: {
    hotCity:[],
    latitude:'23.0999994',
    longitude:'113.324520'
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
//1.选择热门城市
http('get','/api/hot/city',{},"",res=>{
  this.setData({hotCity:res.data})
})
  },
  // 2.点击定位:获取当前经纬度,显示所在城市
  getLocation:function(){
    wx.getLocation({
      success:res=> {
        console.log(res)
        //1。拿经纬度
        var latitude=res.latitude
        var longtitude=res.longitude
        this.setData({
          latitude:res.latitude,
          longitude:res.longitude
        })
        //2.显示位置 获取当前城市名称
        wx.request({
          url: 'http://iwenwiki.com:3002/api/lbs/location',
          data:{
            latitude:latitude,
            longitude:longtitude
          },
          success:result=>{
            console.log(result.data.result.address_component.city.slice(0,2))
            var cityName=result.data.result.address_component.city.slice(0,2);
            //数据存储本地,下一次进入会显示上一次城市
            wx.setStorageSync('cityName', cityName)
            //3.拿到的值返回给list页
            // wx.navigateTo({}) 不能跳转
            // wx.switchTab({
            //   url: '../food/food',
            // })
            // wx.navigateBack({})这两种方法返回时都不能带传参,所以用全局数据方式
            // 方法一:传给全局变量 
            app.globalData.cityName=cityName
            wx.switchTab({
              url: '../food/food',
            })
            //方法二:wx.reLaunch({}),其他跳转是显示隐藏,这个是把其他的关闭,这个页面重新打开(不推荐)
          }
        })
        
      },
    })
  },
  //3.点击热门城市切换当前城市1。点击城市,获取当前城市2.存储到本地和全局
  selectCity:function (e) {
    var cityName=e.currentTarget.dataset.name;
    app.globalData.cityName=cityName;
    wx.setStorageSync('cityName', cityName)
    wx.switchTab({
      url: '../food/food',
    })
    
  },
})

4.查询页面
搜索时用的bindinput方法,实时搜索
在这里插入图片描述

<!-- 搜索 -->
<view class="header">
  <view class="search">
  <input bindinput="searchInput" type="text" focus="true" placeholder="请输入你想要的内容" />
</view> 
</view>
<!-- 搜索内容 -->
<import src="../../templates/foodList/foodList.wxml" />
<view wx:for="{{list}}"  wx:key="index" bindtap="productDetail" data-id="{{item.id}}">
<template is="foodList" data="{{item}}"></template>
</view>
<style>
@import '../../templates/foodList/foodList.wxss'; 

page{
  background: #f1f1f1;
}
.header{
  background: #fff;
  padding: 10rpx;
}
.search{
  background: #f1f1f1;
  border-radius:12rpx ;
  padding: 10rpx;
}
.search input{
  font-size: 28rpx;
  color: #a1a1a1;
  width: 100%;
  height: 100%;
}
</style>
// pages/search/search.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    list: [],
    location: '' //城市
  },
  //搜索输入框内容
  searchInput: function (e) {
    //输入内容 直接查询接口数据-查询名字-城市
    var inputValue = e.detail.value
    if (inputValue) {
      wx.request({
        url: 'http://iwenwiki.com:3002/api/foods/select',
        data: {
          name: inputValue,
          city: this.data.location
        },
        success:res=>{
          // console.log(res.data)
          if(res.data.status==200){
            this.setData({
              list:res.data.data
            })
          }
        }
      })
    } else {
      this.setData({
        list: []
      })
    }
  },
  //进入列表详情
 productDetail:function (e) {
  wx.navigateTo({
    url: '../productDetail/productDetail?itemId='+e.currentTarget.dataset.id,
  })
},
  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
    //获取本地城市,如果有本地,没默认
    var cityName = wx.getStorageSync('cityName') || "北京"
    this.setData({
      location: cityName
    })
  },
})

5.商品列表详情页面
在这里插入图片描述
.wxml

<!-- 详情页面 -->
<swiper class="banner" autoplay="true">
  <swiper-item>
    <image src="../../images/bacg1.jpg"></image>
  </swiper-item>
</swiper>
<!-- 产品名称 -->
<view class="jieshao">{{productInfo.name}}</view>
<!-- 暂无评论 -->
<view class="ping">暂无评论</view>
<!-- 图文信息 -->
<view class="productInfo">
  <view class="xinxi">商品详情</view>
  <image src="{{productInfo.pic}}"></image>
  <view class="desc">
    {{productInfo.description}}
    {{productInfo.details}}
  </view>
</view>
<!-- 购物车 -->
<view class="shopping">
  <view class="shop-img">
    <image src="../../images/cart.png"></image>
  </view>
  <view class="go-shop">加入购物车</view>
  <view class="buy-now">直接购买</view>
</view>

.wxss

<style>
page{
  background: #f1f1f1;
}
.banner{
  width: 100%;
  height: 380rpx;
}
.banner image{
  width: 100%;
  height: 380rpx;
}
.jieshao{
  background-color: #fff;
  padding: 20rpx;
  margin-bottom: 20rpx;
  font-size: 32rpx;
  font-weight: 700;
}
.ping{
  background-color: #fff;
  padding: 20rpx;
  color: #999999;
  font-size: 26rpx;
  margin-bottom: 20rpx;
}
.productInfo{
  background-color: #fff;
  padding: 24rpx;
  margin-bottom: 130rpx;
}
.xinxi{
  color: #666666;
  font-size: 28rpx;
  margin-bottom: 10rpx;
}
.xinxi image{
  width: 100%;
  height: 500rpx;
}
.desc{
  color: #666666;
  font-size: 28rpx;
  line-height: 44rpx;
}
/* 购物车 */
.shopping{
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  border-top:1rpx solid #f9f9f9 ;
  padding: 20rpx;
  background: #fff;
  font-size: 28rpx;
  color: #fff;
}
.shop-img image{
  width: 60rpx;
  height: 60rpx;
}
.shop-img{
  flex: 1;
  text-align: right;
  
}
.go-shop{
  width: 200rpx;
  text-align: center;
  background-color: red;
  padding: 16rpx 0;
  border-radius: 10rpx 0 0 10rpx;
  margin-left: 10rpx;
}
.buy-now{
  width: 200rpx;
  text-align: center;
  background-color: pink;
  padding: 16rpx 0;
  border-radius: 0 10rpx 10rpx 0;
}
</style>

.js

Page({
  /**
   * 页面的初始数据
   */
  data: {
    productInfo:{}
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    wx.request({
      url: 'http://iwenwiki.com:3002/api/foods/list/detail',
      data:{
        id:options.itemId
      },success:res=>{
        this.setData({
          productInfo:res.data.data[0]
        })
      }
    })
  },

})

购物车

在这里插入图片描述
1.加入购物车页面
商品和删除布局通过transform: translateX(90px);transition: all 0.4s;属性设置
功能流程:
1.先请求接口获取购物车里商品信息
2.开始触发坐标
说明:移动list容器view出现删除或隐藏删除按钮,获取第一次触发坐标和移动后坐标 。比较大小,判断左滑还是右滑
3.手指按下后move事件
1.获取滑动坐标点后
2.与开始触发坐标对比
3.小于是左滑显示删除,否则不显示
4.删除
5.计算总价格–每一个选择后计算 总价格=当前list.price*list.num
6.点击选择元素
1.点击选中 再点击取消就是修改当前元素的select状态
2.元素获取下标
3.获取原来的selseted状态
4.获取后 取反 后赋给当前元素
5.判断如果选中的话就数量++
6.更新list数据
7.如果数量大于0,则样式高亮
8.如果数量==list.length,则说明全部选中,全选也要勾选
7.全选按钮
1.获取之前全选按钮状态
2.控制所有list选中框等于全选按钮状态
3.如果选中–处理num 结算高亮
4.更新list数据)
8.增加商品数量
1.num++,增加后页面数据更新–添加给当前元素
2.更新页面list并调接口存到数据库
3.更改价格
9减少商品数量与之相反
.wxml

<!--index.wxml-->
<!-- 购物车布局 -->
<view class="cart">
  <view wx:for="{{list}}" wx:key="index" class="list {{item.isTouchMove?'tuoch-move-active':''}}" bindtouchstart="touchstart" bindtouchmove="touchmove" data-index="{{index}}">
    <view class="item">
      <view class="circle">
        <icon wx:if="{{item.selected}}" bindtap="selectedList" data-index="{{index}}" type="success"></icon>
        <icon wx:else type="circle" bindtap="selectedList" data-index="{{index}}" color="#999"></icon>
      </view>
      <view class="img">
        <image src="{{item.pic}}"></image>
      </view>
      <view class="content">
        <view class="title">{{item.name}}</view>
        <view class="subTitle">{{item.info}}</view>
        <view class="price">{{item.price}}</view>
        <view class="update">
          <view class="reduce" bindtap="deleteShop" data-id="{{item.id}}" data-index="{{index}}">-</view>
          <view class="value">{{item.num}}</view>
          <view class="add" bindtap="addShop" data-id="{{item.id}}" data-num="{{item.num}}" data-index="{{index}}">+</view>
        </view>
      </view>
    </view>
    <view class="remove" bindtap="delete" data-id="{{item.id}}">删除</view>
  </view>
</view>
<view class="bottom">
  <view class="all">
    <icon wx:if="{{selectAllStatus}}" bindtap="selectAll" type="success"></icon>
    <icon wx:else type="circle" bindtap="selectAll" color="#999"></icon>
    <text class="check-all">全选</text>
  </view>
  <view class="sum">
    <text class="he">合计</text>
    <text>{{totalPrice}}</text>
    <text class="small">不含运费</text>
  </view>
  <view class="balance" wx:if="{{selectBtn}}">结算({{totalPrice}})</view>
  <view class="balance-gray balance" wx:else>结算({{totalPrice}})</view>
</view>

.wxss

<style>
page{
  background: #f1f1f1;
}
.cart{
  margin-bottom: 100rpx;
}
.list{
  background: #fff;
  display: flex;
  justify-content: space-between;
  width: 100%;
  overflow: hidden;
  margin-top: 20rpx;
}
/* 左侧内容 */
.item{
  display: flex;
  align-items: center;
  padding: 20rpx;
  width: 100%;
  /* 动画样式 */
  transform: translateX(90px);
  margin-left: -90px;
  transition: all 0.4s;
}
.img image{
  width: 180rpx;
  height: 180rpx;
}
.circle{
  margin-right: 20rpx;
}
.content{
  height: 180rpx;
  position: relative;
  padding-left: 20rpx;
  padding-right: 20rpx;
}
.content .title{
  margin-bottom: 10rpx;
  font-size: 30rpx;
}
.subTitle{
  font-size: 28rpx;
  color: #999;
}
.price{
  position: absolute;
  left: 20rpx;
  bottom: 0;
  color: red;
  font-size: 26rpx;
}
.update{
  position: absolute;
  bottom: 0;
  right: 20rpx;
  left: 250rpx;
  width: 200rpx;
  display: flex;
}
.reduce,.add{
  width: 40rpx;
  height: 40rpx;
  border: 1rpx solid #999999;
  text-align: center;
  line-height: 40rpx;
}
.value{
  width: 100rpx;
  text-align: center;
}
/* 右侧删除 */
.remove{
  background-color: red;
  color: #fff;
  width: 90px;
  justify-content: center;
  display: flex;
  align-items: center;
  /* 默认隐藏 */
  transform: translateX(90px);
  transition: all 0.4s;
}
/* 当鼠标按下添加拖拽改变 */
.tuoch-move-active .item,.tuoch-move-active .remove{
  transform: translateX(0);
}
.bottom{
  position: fixed;
  bottom: 0;
  padding: 5px 0;
  display: flex;
  background-color: #fff;
  font-size: 30rpx;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}
.all{
  flex: 1;
}
.all icon{
  vertical-align: middle;
  margin-left: 20rpx;
}
.check-all{
  font-weight: 600;
  margin-left: 5rpx;
}
.balance{
  text-align: center;
  width: 180rpx;
  background-color:#43bf92;
  padding: 20rpx 10rpx;
  color: #fff;
  margin-left: 10rpx;
}
.he{
  font-weight: 600;
}
.small{
  font-size: 24rpx;
  color: #999;
  margin: 0 0 0 10rpx;
}
.balance-gray{
  background-color: #999999;
}
</style>

.js

// pages/food/food.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    selected: false, //当前是否选中
    startX: 0,
    startY: 0, //开始坐标
    list: [], //购物车数据
    selectBtn: false,
    selectAllStatus: false,
    totalPrice: '0.00',
    num: 0 //选中数量
  },
  //1.开始触发坐标
  // 说明:移动list容器view出现删除或隐藏删除按钮,获取第一次触发坐标和移动后坐标 。比较大小,判断左滑还是右滑
  touchstart: function (e) {
    this.setData({
      startX: e.changedTouches[0].clientX,
      startY: e.changedTouches[0].clientY
    })
  },
  //2.手指按下后move事件
  touchmove: function (e) {
    // console.log(e)
    //获取滑动坐标点
    var index = e.currentTarget.dataset.index
    var startX = this.data.startX
    var startY = this.data.startY //开始坐标
    var moveX = e.changedTouches[0].clientX
    var moveY = e.changedTouches[0].clientY
    //判断movex和startx大小,判断左滑右滑
    var list = this.data.list;
    //如果控制只有一个元素可以左滑
    for (var i = 0; i < list.length; i++) {
      list[i].isTouchMove = false
    }
    if (moveX < startX) { //左滑
      list[index].isTouchMove = true
    } else {
      list[index].isTouchMove = false
    }
    //更新数据
    this.setData({
      list: list
    })
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {

  },
  //3.购物车方法
  getShop: function () {
    wx.request({
      url: 'http://iwenwiki.com:3002/api/cart/list',
      success: res => {
        if (res.data.status == 200) {
          this.setData({
            list: res.data.data.result
          })
        }
      }
    })
  },
  //4.删除按钮
  delete: function (e) {
    var id = e.currentTarget.dataset.id;
    wx.request({
      url: 'http://iwenwiki.com:3002/api/cart/delete',
      data: {
        id: id
      },
      success: res => {
        if (res.data.status == 200) {
          wx.showToast({
            title: '删除成功',
            icon: 'none'
          })
          this.getShop()
        }
      }
    })
  },
  //5.计算总价格==每一个选择后计算 总价格=当前list.price*list.num
  goTotalPrice: function () {
    //1.获取所有元素list2.查看所有数据 选中元素 3.计算
    var list = this.data.list;
    var total = 0;
    for (var i = 0; i < list.length; i++) {
      if (list[i].selected) {
        total += list[i].price * list[i].num
      }
    }
    this.setData({
      totalPrice: total.toFixed(2)
    })
  },
  //6.点击选择元素
  //1.点击选中 再点击取消就是修改当前元素的select状态 2.元素下标
  selectedList: function (e) {
    var index = e.currentTarget.dataset.index;
    var list = this.data.list;
    var num = this.data.num;
    //获取原来的selseted状态
    var selected = list[index].selected;
    //获取后 取反 后赋给当前元素
    list[index].selected = !selected
    //3.选中框,num++
    if (list[index].selected) {
      num++
    } else {
      num--
    }
    //4.更新list数据
    this.setData({
      list: list,
      num: num
    })
    //5.结算变高亮
    if (num > 0) {
      this.setData({
        selectBtn: true
      })
    } else {
      this.setData({
        selectBtn: false
      })
    }
    // 6.全选
    if (num == list.length) {
      this.setData({
        selectAllStatus: true
      })
    } else {
      this.setData({
        selectAllStatus: false
      })
    }
    this.goTotalPrice()
  },
  //7.全选 
  selectAll: function () {
    //1.获取之前全选状态
    var selectAllStatus = !this.data.selectAllStatus
    var list = this.data.list
    var num = this.data.num
    var selectBtn = this.data.selectBtn
    //2.控制所有list选中框
    for (var i = 0; i < list.length; i++) {
      list[i].selected = selectAllStatus
    }
    // 3.如果选中--处理num 结算高亮
    if (selectAllStatus) {
      num = list.length;
      selectBtn = true
    } else {
      num = 0;
      selectBtn = false
    }
    //  4.更新list数据
    this.setData({
      list: list,
      num: num,
      selectBtn: selectBtn,
      selectAllStatus: selectAllStatus
    })
    this.goTotalPrice()

  },
  // 8.增加购物车数量
  addShop: function (e) {
    var num = e.currentTarget.dataset.num
    var index = e.currentTarget.dataset.index
    var id = e.currentTarget.dataset.id
    num++;
    //增加后页面数据更新==添加给当前元素
    var list = this.data.list
    list[index].num = num;
    //更新
    this.setData({
      list: list
    })
    //网络请求,修改数据库里数据
    wx.request({
      url: 'http://iwenwiki.com:3002/api/cart/update',
      data: {
        id: id,
        num: num
      }
    })
    //更改价格
    this.goTotalPrice()
  },
  //9.--功能
  deleteShop: function (e) {
    var index = e.currentTarget.dataset.index
    var id = e.currentTarget.dataset.id
    //增加后页面数据更新==添加给当前元素
    var list = this.data.list
    if (list[index].num < 2) {
      wx.showToast({
        title: '数量最少为1',
        icon: "none"
      })
      return
    } else {
      list[index].num--
    }
    //更新
    this.setData({
      list: list
    })
    //网络请求,修改数据库里数据
    wx.request({
      url: 'http://iwenwiki.com:3002/api/cart/update',
      data: {
        id: id,
        num: list[index].num
      }
    })
    //更改价格
    this.goTotalPrice()
  },


  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {
    this.getShop()
    this.setData({
      selectBtn: false,
      selectAllStatus: false,
      totalPrice: '0.00',
      num: 0 //选中数量
    })
  },
})

2.详情页面加入购物车
给按钮绑定事件
.wxml

<!-- 购物车 -->
<view class="shopping">
  <view class="shop-img">
    <image src="../../images/cart.png" bindtap="goShop"></image>
  </view>
  <view class="go-shop" bindtap="addShop">加入购物车</view>
  <view class="buy-now">直接购买</view>
</view>

.js

  //1.加入购物车
  addShop: function () {
    var productInfo=this.data.productInfo
    wx.request({
      url: 'http://iwenwiki.com:3002/api/cart/add',
      data:{
        name:productInfo.name,
        pic:productInfo.pic,
        num:1,
        info:productInfo.description,
        price:productInfo.price
      },success:res=>{
        if(res.data.status==200){
          wx.showToast({
            title: '添加成功',
            icon:'none'
          })
        }
      }
    })
  },
  // 2.点击进入购物车页面
  goShop:function () {
    wx.switchTab({
      url: '../myCart/myCart',
    })
  },
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值