美文网首页微信应用号开发微信小程序
仿洗衣小程序开发经验分享

仿洗衣小程序开发经验分享

作者: dreamlv0703 | 来源:发表于2017-07-31 15:51 被阅读963次

    解决问题,方便生活,为大学校园中,企业园区里洗衣服还要办理洗衣卡,洗衣服的时候还得揣着一张洗衣卡,只需要拿着手机扫一扫就能完美解决,畅洗洗衣微信小程序。下来看看该小程序“畅洗”,本人写了几个自己觉得主要的功能,还有部分功能待编写中,欢迎各位看官批评,同时跪求各位看官收藏点赞,不胜感激,上效果图:


    概览.gif

    注:PC端无法实现扫码,弹出打开文件框

    一、准备工作

    小程序吗,慢慢玩儿,微信给玩家提供了一大推你所需要的各种各种,你只要一个微信号就行。在开发小程序时,对小程序有个大概的认识就行,不求多牛逼,记得我心目中的大佬说过,不要发等你好牛逼了才来做牛逼的事,慢慢做,碰到问题解决问题,你就能牛逼起来,一台PC,同时匹配PC下载好微信小程序的开发者工具,编辑器,有很多种,本人用的VSCode,接下来就开始干了。

    二、前期开发工作

    打开微信公众平台网页见地址:https://mp.weixin.qq.com/,实名注册一个,扫码登录微信公众平台,点击设置->开发设置拿到属于自己的专属AppID(小程序ID),详见下图:

    小程序ID.png
    复制该AppID(小程序ID)至微信开发者工具,取名、选定文件夹 -> 添加项目,得到的页面又是这样的:
    Hello World.png
    单击左上角编辑,出现如下界面:
    tree.png
    pages文件夹下存放着小程序所有的业务功能实现页面,一般默认有俩,分别为index和logs;
    index文件夹就是一个页面,index.wxml是页面的结构文件,类似html。
    index.wxss是页面的样式,其实就是css;
    index.js是页面的逻辑,数据请求与渲染都是都在这个页面完成。
    logs文件夹存放着小程序开发日志,目前暂时用不到。
    utils.js可以编写自己的JavaScript插件。
    app.js处理全局的一些逻辑,比如定义全局变量存放获取的用户信息,这样每个页面都可以获取用户信息。
    app.json 是全局配置文件,比如设置标题栏的背景色等。
    app.wxss 存放页面的公共样式,如果多个页面需要用到同一样式,就可以写在这里。
    项目按钮显示预览二维码,用于真机调试。必须真机调试测试代码
    更加详细的文档参见:
    https://mp.weixin.qq.com/debug/wxadoc/dev/framework/config.html?t=20161230
    还有微信ui库的地址:https://weui.io/

    三、分析业务创建所需页面结构

    1、首先分析我们做的小程序有哪些需要用到的业务,创建相应的page,即在app.json文件里添加相应的代码,下图是我的.json页面:


    myjson.png

    创建了相应的page,同时删除了原有的Index和logs。
    2、编写相应的通用样式,在app.wxss文件里编写,我就啥也没写,还注释了里面的代码。
    3、经过上述第一步搭建好了页面结构,同事一样,上波图,更直观:


    mytree.png

    四、页面设计效果

    1、首页大图,也是标志性的Logo(logo文件夹)


    logo.gif

    该页面跳转设计了点击跳转和定时跳转两种跳转方式,点击跳转可能.gif文件展示的不是很好
    logo.js代码:

     bindLogoTap: function() {
        wx.navigateTo({
          url: '../iconInformation/iconInformation'
        })
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        // 设置初始计时秒数
        let time = 2;
        // 开始定时器
        this.timer = setInterval(() => {
          this.setData({
            time: -- time
          });
          // 读完秒后携带洗衣机编号跳转到计费页
          if(time < 0){
            clearInterval(this.timer)
            wx.navigateTo({
              url: '../iconInformation/iconInformation'
            })
          }
        },1000)
       
      },
    

    logo.wxml代码:

    <view class="logo">
      <image bindtap="bindLogoTap" class="logo_page" src="/images/logo.jpg" mode="widthFix"></image>
    </view>
    

    样式代码就不贴了,就用图片充满屏幕就行了。
    2、主要处理页面,也是坑的我最惨的,一个抽屉栏我就半天出不来自己想要的效果,后找了猛人帮忙,搞定了,在此感谢,见下图:


    抽屉.gif

    .js代码如下,轻松愉快的一个自定义函数搞定,不想我之前的绕绕绕,然后我自己都不知道了

    Page({
        data: {
            translate: '',
            showPageBottom: false
        },
    
        
        showMenu: function() {
            this.setData({
                showPageBottom: !this.data.showPageBottom
            })
        },
    }
    

    .wxml代码如下,图片绑定事件

    <view class="page-bottom {{showPageBottom?'active':''}}">
    

    3、业务界面,这里面设计的业务不是很多,就一张一张图片贴了。

    3.1、点击信息小图标,进入到sms业务界面,图片如下:


    消息.png

    3.2、用户信息页,抽屉栏最上方小型logo图标出现,如下图:


    用户信息.gif
    部分js代码如下,单选按钮默认选中“男”
    data: {
        items: [
          {name: 'men', value: '男', checked: 'true'},
          {name: 'women', value: '女'},
        ]
      },
      radioChange: function(e) {
        console.log('radio发生change事件,携带value值为:', e.detail.value)
      },
    

    3.3、我的钱包页,点击我的钱包就好了,页面跳转后又有如果不选定金额,下面的提交按钮默认是灰色的,这是点击提交按钮出现的用户反馈信息弹窗;同时点击按钮的时候就提交按钮就变色显示,可选择充值金额,效果图如下:


    我的钱包.gif

    部分js代码如下:

    // pages/wallet/wallet.js
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
          // 充值数额类型数组
        checkboxValue: [],
        // 提交按钮的背景色,未勾选类型时无颜色
        btnBgc: "",
        // 复选框的value,此处预定义,然后循环渲染到页面
        itemsValue: [
          {
            checked: false,
            value: "充值¥10轻币",
            color: "#b9dd08"
          },
          {
            checked: false,
            value: "充值¥20轻币",
            color: "#b9dd08"
          },
          {
            checked: false,
            value: "充值¥50轻币",
            color: "#b9dd08"
          },
          {
            checked: false,
            value: "充值¥60轻币",
            color: "#b9dd08"
          },
          {
            checked: false,
            value: "充值¥80轻币",
            color: "#b9dd08"
          },
          {
            checked: false,
            value: "充值¥100轻币",
            color: "#b9dd08"
          }
        ]
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      // 页面加载
      onLoad:function(options){
        wx.setNavigationBarTitle({
          title: '我的钱包'
        })
      },
    // 勾选充值金额,获取类型值存入checkboxValue
      checkboxChange: function(e){
        let _values = e.detail.value;
        if(_values.length == 0){
          this.setData({
            btnBgc: ""
          })
        }else{
          this.setData({
            checkboxValue: _values,
            btnBgc: "#b9dd08"
          })
        }   
      },
    // 输入充值金额,存入inputValue
      numberChange: function(e){
        this.setData({
          inputValue: {
            num: e.detail.value,
            desc: this.data.inputValue.desc
          }
        })
      },
    // 输入备注,存入inputValue
      descChange: function(e){
        this.setData({
          inputValue: {
            num: this.data.inputValue.num,
            desc: e.detail.value
          }
        })
      },
    // 提交到服务器
      formSubmit: function(e){
        if(this.data.checkboxValue.length> 0){
          wx.request({
            url: 'https://www.easy-mock.com/mock/59098d007a878d73716e966f/ofodata/msg',
            data: {
            },
            method: 'get', 
            success: function(res){
              wx.showToast({
                title: res.data.data.msg,
                icon: 'success',
                duration: 2000
              })
            }
          })
        }else{
          wx.showModal({
            title: "请填写反馈信息",
            content: '你宝贵的意见是我们改进的方向',
            confirmText: "如实填写",
            cancelText: "忽略",
            success: (res) => {
              if(res.confirm){
                // 继续填
              }else{
                console.log("back")
                wx.navigateBack({
                  delta: 1 // 回退前 delta(默认为1) 页面
                })
              }
            }
          })
        }   
      }
    })
    

    3.4、优惠券页,效果图如下:


    优惠券.gif

    3.5、我的洗衣机页,查看当前已绑定的洗衣机,还可申请绑定或是租赁相应的洗衣机,效果图如下:


    我的洗衣机.png
    3.6、设置页,相关设置均在此,上效果图吧,如下:
    设置.png

    3.7、推荐给好友,这一页来点不同的,就写模块待开发


    推荐给好友.gif
    3.8、点我洗衣,主页面下方点我洗衣,效果图如下: logo.png 点我洗衣.gif 扫码.jpg

    拖动位置点击重新定位回到当前位置,另由于PC端扫码功能更不一样为打开文件形式,上的真机测试截图。貌似有点不伦不类,还请各位看官见谅。。。
    js代码

    //myoption.js
    //获取应用实例
    var app = getApp()
    Page({
      data: {
        scale: 18,
        latitude: 22.650529,
        longitude: 113.925354
      },
    // 页面加载
      onLoad: function (options) {
        // 1.获取定时器,用于判断是否在洗衣
        this.timer = options.timer;
    
        // 2.获取并设置当前位置经纬度定位
        wx.getLocation({
          type: "gcj02",
          success: (res) => {
            this.setData({
              longitude: res.longitude,
              latitude: res.latitude
            })
          }
        });
    
        // 3.设置地图控件的位置及大小,通过设备宽高定位
        wx.getSystemInfo({
          success: (res) => {
            this.setData({
              controls: [{
                id: 1,
                iconPath: '/images/location.png',
                position: {
                left: 20,
                top: res.windowHeight - 80,
                width: 50,
                height: 50
                },
                clickable: true
              },
              {
                id: 2,
                iconPath: '/images/use.png',
                position: {
                left: res.windowWidth/2 - 45,
                top: res.windowHeight - 100,
                width: 90,
                height: 90
                },
                clickable: true
              },
              {
                id: 3,
                iconPath: '/images/warn.png',
                position: {
                left: res.windowWidth - 70,
                top: res.windowHeight - 80,
                width: 50,
                height: 50
                },
                clickable: true
              },
              {
                id: 4,
                iconPath: '/images/marker.png',
                position: {
                left: res.windowWidth/2 - 11,
                top: res.windowHeight/2 - 45,
                width: 22,
                height: 45
                },
                clickable: true
              },
              {
                id: 5,
                iconPath: '/images/avatar.png',
                position: {
                left: res.windowWidth - 68,
                top: res.windowHeight - 155,
                width: 45,
                height: 45
                },
                clickable: true
              }]
            })
          }
        });
    
        // 4.请求服务器,显示附近的洗衣机,用marker标记
        wx.request({
          url: 'http://easy-mock.com/mock/596d6dbea1d30433d835cab0/query/list',
          data: {},
          method: 'GET', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT
          // header: {}, // 设置请求的 header
          success: (res) => {
              this.setData({
                markers: res.data.data
              })
          },
          fail: function(res) {
            // fail
          },
          complete: function(res) {
            // complete
          }
        })
      },
    // 页面显示
      onShow: function(){
        // 1.创建地图上下文,移动当前位置到地图中心
        this.mapCtx = wx.createMapContext("QingKeMap");
        this.movetoPosition()
      },
    // 地图控件点击事件
      bindcontroltap: function(e){
        // 判断点击的是哪个控件 e.controlId代表控件的id,在页面加载时的第3步设置的id
        switch(e.controlId){
          // 点击定位控件
          case 1: this.movetoPosition();
            break;
          // 点击立即洗衣,判断当前是否正在计时
          case 2: if(this.timer === "" || this.timer === undefined){
              // 没有在计费就扫码
              wx.scanCode({
                success: (res) => {
                  // 正在获取密码通知
                  wx.showLoading({
                    title: '洗衣准备',
                    mask: true
                  })
                  // 请求服务器获取密码和洗衣机
                  wx.request({
                    url: 'http://easy-mock.com/project/596d6dbea1d30433d835cab0/query',
                    data: {},
                    method: 'GET', 
                    success: function(res){
                      // 请求密码成功隐藏等待框
                      wx.hideLoading();
                      // 携带密码和洗衣机编号跳转到密码页
                      wx.redirectTo({
                        url: '../scanresult/index?password=' + res.data.data.password + '&number=' + res.data.data.number,
                        success: function(res){
                          wx.showToast({
                            title: '获取密码成功',
                            duration: 1000
                          })
                        }
                      })           
                    }
                  })
                }
              })
            // 当前已经在计费就回退到计费页
            }else{
              wx.navigateBack({
                delta: 1
              })
            }  
            break;
          default: break;
        }
      },
    // 地图视野改变事件
      bindregionchange: function(e){
        // 拖动地图,获取附件洗衣机位置
        if(e.type == "begin"){
          wx.request({
            url: 'http://easy-mock.com/mock/596d6dbea1d30433d835cab0/query/list',
            data: {},
            method: 'GET', 
            success: (res) => {
              this.setData({
                _markers: res.data.data
              })
            }
          })
        // 停止拖动,显示单车位置
        }else if(e.type == "end"){
            this.setData({
              markers: this.data._markers
            })
        }
      },
    // 地图标记点击事件,连接用户位置和点击的单车位置
      bindmarkertap: function(e){
        console.log(e);
        let _markers = this.data.markers;
        let markerId = e.markerId;
        let currMaker = _markers[markerId];
        this.setData({
          polyline: [{
            points: [{
              longitude: this.data.longitude,
              latitude: this.data.latitude
            }, {
              longitude: currMaker.longitude,
              latitude: currMaker.latitude
            }],
            color:"#FF0000DD",
            width: 1,
            dottedLine: true
          }],
          scale: 18
        })
      },
    // 定位函数,移动位置到地图中心
      movetoPosition: function(){
        this.mapCtx.moveToLocation();
      }
    })
    

    wxml文件

    <view class="container">
      <map id="QingKeMap" latitude="{{latitude}}" longitude="{{longitude}}" scale="{{scale}}" bindregionchange="bindregionchange" polyline="{{polyline}}" markers="{{markers}}" controls="{{controls}}" bindmarkertap="bindmarkertap"  bindcontroltap="bindcontroltap" show-location/>
    </view>
    

    五、扩展总结

    由于服务器和本人技术问题,这里免得数据使用的是easy-mock伪造数据;easy-mock可以作为前端开发的伪后端,自己构造数据来测试前端代码。方便又快捷。官网戳这里
    同时使用了一些微信小程序的官方API,如:
    扫码API: wx.scanCode({})
    向服务器发送请求:wx.request({})
    显示加载框: wx.showLoading()
    隐藏加载框: wx.hideLoading()
    显示提示框: wx.showToast()
    隐藏提示框: wx.hideToast()
    关闭当前页面,跳转到指定页面: wx.redirectTo({})
    保留当前页面,跳转到指定页面: wx.navigateTo({})
    回退到指定页面: wx.naivgateBack({})
    一些详细用法和更多其他的API请查看微信小程序API文档
    小结:畅洗洗衣下程序也弄得七七八八了,剩下还有一些功能待接下来继续完成,本人开发过程中遇到过很多的坎,有一个个人觉得最重要的效果显示(抽屉栏菜单)好久都没有做出自己的想要的效果,查了N多资料,就是搞不定,最后请教大佬实例操作一波,几行子代码替代我几十行代码搞定,最重要的是我的几十行还实现不了,这就很尴尬了吧,咸鱼还是得努力翻身啊!不会的找大神,提点几句自己动手做能解决最好了,实在不行,请教大佬实地地操作一波了,搞定了自己还得好好悟,努力进步就是最好的。在此跪求各位看官不吝啬点点手指的力气去,点点手指,收藏,点赞,喜欢能来的就来一波,小的跪求。。。。。。
    同时源码在小的的github上,有需要的欢迎fork
    附注:本人求职中,坐标深圳,同时不介意北上广杭等互联网发展聚集地,
    联系方式:电话:18770919203 邮箱:1412453932@qq.com/18770919203@163.com
    欢迎骚扰!!!

    相关文章

      网友评论

      • 居客侠:对一个在校大学生来说,能独自做出来这个demo已经很不错了。欢迎来上海安居客公司,我们已经开发出了安居客小程序,你可以微信小程序搜索“安居客”。我们缺一个小程序开发人员,虽然它现在是我在维护。:joy: 一起来玩小程序吧。有意向可以私信我。
      • ThinkNuo:抽屉效果那个学过 React 就很好实现,通过 state 来改变 View 状态

      本文标题:仿洗衣小程序开发经验分享

      本文链接:https://www.haomeiwen.com/subject/krxrlxtx.html