微信小程序踩坑记

搭建环境

按照官方的简易教程搭建。微信小程序简易上手

网上查找开源项目

在github上面查找开源项目,以供上手。准备开发一个电商小程序,因此找了wechat-weapp-mall

因为是个人练手项目,没有素材,直接使用了该项目的素材,然后模仿开发。

页面设计

  • 首页
  • 分类
  • 购物车、订单
  • 个人信息
  • 其他各种功能尝试,暂时没头绪,后续添加。

使用小程序默认项目,对面模块建立对应的目录

  • index
  • classify
  • order
  • userinfo

在app.json的pages中引入对应的模块。

开发首页

首页功能列表

  • 扫一扫、搜索框、交流信息
  • 轮播
  • 分栏商品
  • 底部(共有导航模块)

扫一扫、搜索框、交流信息。

事件绑定使用bindtap,扫码使用接口scanCode,扫码API

注意:本地图片资源不能使用,因此要使用网络图片资源。

<image class="sort-icon" src='/images/扫一扫.png'  bindtap="saoyisao"></image>
  saoyisao: function () {
    //扫码
    wx.scanCode({
      success: (res) => {
        console.log(res)
      }
    });
  }

搜索框实现,样式搞了好久。联想输入框有待实现。

  • wxss
.sort-input {
  width: 75%;
  border: 1rpx solid #ddd;
  border-radius: 5rpx;
}

.sort-input-bg {
  /* background:bg-color bg-image position/bg-size bg-repeat bg-origin bg-clip bg-attachment initial|inherit;  */
  background: url("https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1507043922110&di=2f65bebf9975e79f0642058c4dbb2bfb&imgtype=0&src=http%3A%2F%2F58pic.ooopic.com%2F58pic%2F14%2F64%2F63%2F96u58PICfAj.jpg");
  background-size: 40rpx 40rpx;
  background-repeat: no-repeat;
  background-position: 5rpx;
}

.input-word {
  font-size: 32rpx;
  color: gainsboro;
  padding-left: 60rpx;
}
  • wxml,通过bindinput来进行数据绑定。class里面的插值表达式来进行样式的变动。
    <input class="sort-input {{inputValue == '' ? 'sort-input-bg':''}}" type="text" bindinput="bindKeyInput" placeholder="IPhone 8" placeholder-class="input-word"> </input>
    
<!-- <view class="section__title">你输入的是:{{inputValue}}</view> -->
  • js,键盘输入事件。
bindKeyInput: function(e) {
    this.setData({
      inputValue: e.detail.value
    })
  }

交流信息,即客服等等有待实现。

轮播+路由跳转开发

使用swiper标签进行开发,记得设置元素的高宽度。

  • index.wxml
  <swiper class="index-swiper" indicator-dots="{{indicatorDots}}" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}">
    <block wx:for="{{imgUrls}}">
      <swiper-item>
      <navigator url='{{item.path}}' >
        <image src="{{item.img}}" class="index-swiper" width="355" height="150" />
      </navigator>
      </swiper-item>
    </block>
  </swiper>
  • index.js
  data: {
    imgUrls: [
      { path:'/pages/classify/classify',img:'http://img02.tooopen.com/images/20150928/tooopen_sy_143912755726.jpg'},
      { path: '/pages/classify/classify',img:'http://img06.tooopen.com/images/20160818/tooopen_sy_175866434296.jpg'},
      { path: '/pages/classify/classify',img:'http://img06.tooopen.com/images/20160818/tooopen_sy_175833047715.jpg'}
    ],
    indicatorDots: true,
    autoplay: true,
    interval: 2000,
    duration: 1000
  },
  • index.wxss
.index-swiper {
 height: 400rpx;
 width: 100%;
}

竖型轮播

<view class="hot">
    <view class="hot-title">
      <icon type="success" size="40" />
    </view>
    <view class="hot-content">
      <swiper class="hot-swiper" vertical="true" autoplay="{{autoplay}}" interval="{{interval}}" duration="{{duration}}">
        <block wx:for="{{hot_data}}">
          <swiper-item>
            <navigator url='{{item.path}}'>
              <text class="h-title">{{item.title}}</text>
              <text class="h-content">{{item.content}}</text>
            </navigator>
          </swiper-item>
        </block>
      </swiper>
    </view>
  </view>

加入购物车

  • wxml,使用bindtap绑定点击事件,data-p传值
<image class="add-to-car" src='/images/buy.png' bindtap="addToCar" data-p="{{item}}"></image>
  • js,这里传递的是一个事件,事件里面的target.dataset便是我们传递的值,此处使用了app.js里面的全局变量来存值。
  addToCar: function(event) {
    getApp().globalData.carList.push(event.target.dataset.p);
  }

底部导航

在app.json中添加如下代码即可,如果内容页的导航地址有跟底部导航一样的跳不过去。

  "tabBar": {
    "color": "#6e6d6b",
    "selectedColor": "#f9f027",
    "borderStyle": "white",
    "backgroundColor": "#292929",
    "list": [{
      "pagePath": "pages/index/index",
      "iconPath": "images/footer-icon-01.png",
      "selectedIconPath": "images/footer-icon-01-active.png",
      "text": "极速免税"
    }, {
      "pagePath": "pages/classify/index",
      "iconPath": "images/footer-icon-02.png",
      "selectedIconPath": "images/footer-icon-02-active.png",
      "text": "分类"
    }, {
      "pagePath": "pages/cart/index",
      "iconPath": "images/footer-icon-03.png",
      "selectedIconPath": "images/footer-icon-03-active.png",
      "text": "购物车"
    }, {
      "pagePath": "pages/my/index",
      "iconPath": "images/footer-icon-04.png",
      "selectedIconPath": "images/footer-icon-04-active.png",
      "text": "我的"
    }]
  }

购物车、支付

模拟购物车

使用checkbox,wx:for在数组会变的情况下,尽量使用wx:key。微信支付功能由于条件不具备,因此只是使用了模态框模拟。

  • wxml
<view class="container">
  <view class="list" wx:if="{{hasProduct}}">
    <view class="car-product">
      <checkbox-group class="car-checkbox" bindchange="choice">
        <lable class="car-label" wx:for="{{productList}}" wx:key="item.id">
          <view class="p-img">
            <checkbox class="pp-check" value="{{item.id}}" checked="{{item.checked}}" />
            <image class="pp-img" src="{{item.img}}"></image>
          </view>
          <view class="p-detail">
            <view class="p-name">
              {{item.name}}
            </view>
            <view class="p-price">
              ¥{{item.price}} x {{item.count}}
            </view>
          </view>
        </lable>
      </checkbox-group>
    </view>
    <button class="buy" bindtap="buy">支付</button>
  </view>
  <view class="empty" wx:else="{{hasProduct}}">
    <image src="/images/cart-null.png" class="car-null"></image>
    <view class="car-null">购物车空空如也</view>
  </view>
</view>
  • js, onShow是每次显示页面的时候都会调用次方法。
//index.js
//获取应用实例
const app = getApp()

Page({
  data: {
    //页面数据初始化
    hasProduct: false,
    productList: []
  },
  onLoad: function (options) {
    //监听页面加载,页面初始化,options为页面跳转所带来的参数
    // 检查是否登录
    wx.checkSession({
      success: function () {
        console.log("已经登录");
      },
      fail: function () {
        //登录态过期
        app.globalData.login();
      }
    });
  },
  onReady: function () {
    //监听页面渲染完成
  },
  onShow: function () {
    //监听页面显示
    // this.data.productList = app.globalData.carList;
    if (app.globalData.carList.length > 0) {
      this.setData({
        productList: app.globalData.carList,
        hasProduct: true
      });
    }
  },
  onHide: function () {
    //监听页面隐藏
  },
  onUnload: function () {
    //监听页面卸载
  },
  choice: function (event) {
    wx.setStorageSync('buyIds', event.detail.value);
  },
  buy: function () {
    console.log(wx.getStorageSync('buyIds'));

    wx.showModal({
      title: '支付提示',
      content: '总金额:¥100000000000',
      confirmText: '支付',
      success: function (res) {
        if (res.confirm) {
          wx.requestPayment({
            'timeStamp': '',
            'nonceStr': '',
            'package': '',
            'signType': 'MD5',
            'paySign': '',
            'success': function (res) {
              wx.navigateTo({
                url: '/pages/order/order'                
              });
            },
            'fail': function (res) {
              console.log(res);
              wx.navigateTo({
                url: '/pages/order/order'                
              });
            }
          })
          wx.showModal({content: '模拟支付'});
        } else if (res.cancel) {
          console.log('取消支付')
        }
      }
    });
  }
});

  • wxss,多个class需要逗号分开。多选框位置偏下,不知道如何调,以后想方法。
.container, .list, .car-product{
  width: 100%;
}
.car-null{
  width: 500rpx;
  height: 500rpx;
  align-items: center;
}

.car-label {
  width: 100%;
  height: 150rpx;
}
.p-img{
  width: 45%;
  height: 150rpx;
  display: inline-block;
}
.pp-check {
  width: 20%;
  display: inline-block;
  padding-left: 10rpx;
}
.pp-img{
  width: 60%;
  height: 150rpx;
  padding-left: 10rpx;
  padding-right: 10rpx;
  display: inline-block;
}
.p-detail{
  width: 50%;
  height: 150rpx;
  display: inline-block;
  padding-left: 10rpx;
}

.p-name {
  width: 100%;
  height: 75rpx;

}

.p-price {
  width: 100%;
  height: 75rpx;
}

.buy {
  /* position: fixed; */
  /* right: 0rpx;
  bottom: 0rpx; */
  position:absolute;
  right:0px;
  bottom:0px;
  border:1px solid #aaa;
}

因为没有后台,其他页面不进行模拟了,下面学习小程序的地图等功能。

地图使用。

实现了获取当前位置,订单轨迹、打电话功能

  • wxml
<view class="container">
  <map id="map" longitude="{{longitude}}" latitude="{{latitude}}" scale="14"
   controls="{{controls}}" 
    markers="{{markers}}" 
     polyline="{{polyline}}" 
      show-location style="width: 100%; height: 300px;">
    </map>
    <button bindtap="showLine">显示订单轨迹</button>
    <button bindtap="telphone" data-phone="15920971897">打电话给快递员</button>
</view>
  • js
//index.js
//获取应用实例
const app = getApp()

Page({
  data: {
    latitude: 0,
    longitude: 0,
    markers: [],
    polyline: [],
    controls: []
  },

  onLoad: function (options) {
    //监听页面加载,页面初始化,options为页面跳转所带来的参数
  },
  onReady: function () {
    //监听页面渲染完成
  },
  onShow: function () {
    //监听页面显示
    const _this = this;
    wx.getLocation({
      type: 'wgs84',
      success: function (res) {
        _this.setData({
          latitude: res.latitude,
          longitude: res.longitude,
          markers: [{
            iconPath: "/images/location.png",
            id: 0,
            latitude: res.latitude,
            longitude: res.longitude,
            width: 50,
            height: 50
          }]
        });
      }
    })
  },
  onHide: function () {
    //监听页面隐藏
  },
  onUnload: function () {
    //监听页面卸载
  },
  showLine: function () {
    let points = []
    points.push({ longitude: this.data.longitude, latitude: this.data.latitude });
    for (var index = 0; index < 10; index++) {
      let lg = this.data.longitude + Math.random() * 0.1;
      let lt = this.data.latitude + Math.random() * 0.1;
      points.push({ longitude: lg, latitude: lt });
    }
    this.setData({
      polyline: [{
        points: points,
        color: "#FF0000DD",
        width: 2,
        dottedLine: true
      }]
    });
  },
  telphone: function (event) {
    wx.makePhoneCall({
      phoneNumber: event.target.dataset.phone
    })
  }
})

小结

基本上掌握了小程序的开发流程,个人感觉小程序的核心是如何设计漂亮的UI,剩余的都是调用小程序原有的接口便能满足。如果是前端工程师转入小程序就是零难度。

站在巨人的肩膀上,一个APP就是那么的简单。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容