关于小程序的开发心得

1 前言

本人不是专门从事设计的人,但是空闲时间也会关注一些设计方面的知识。这段时间做了差不多4-5个小程序,基本上小程序上通用的接口都使用过了。本文对于在开发文档上已经描写清楚的不会过多进行讲述。

2 设计

2.1 写给新手设计师

如果你不是属于对于手机端设计很有心得的大牛的话,我还建议你先上微信公众号的小程序设计指南认真观看,网站如下:
微信设计指南
在文章的最后有提供微信风格的基础控件库下载,这个可以让你快速熟悉微信上所具有的一些控件。在首次做小程序设计的时候,尽量不要说是只做一个完完全全静态的小程序界面,我觉得小程序本身应该更加注重的是UE(即用户体验)和IxD(用户交互),所以你可在不考虑美观性多强前,先尝试着将控件放入设计中。
我个人觉得你的界面可以做的一般般,但是一个好的交互和体验,对于用户的感官会更加的舒服。而且我见过几个小程序设计图。我个人感觉小程序在美观上不如APP或web APP,也许是我做过的几套里的设计都太一般了吧。但是小程序的体验交互还是不错的。

2.2 尺寸说明

对于小程序的设计,个人比较建议还是以iphone6为主,我觉得这个尺寸下的图会更接近于手机上的效果,而且更方便与开发人员的开发。按照微信小程序配套的尺寸单位计算来看:
我们会发现iphon6的屏幕下对于尺寸的计算会更加方便,为2:1。
在这里插入图片描述

3 开发

3.1 概述

我们生成项目目录后,基本可以分为两类,一类以app命名的文件,就是作为一个全局配置文件,一类是自定义的page文件,像pages/log下定义的页面本身的文件。
关于page文件,一个page文件需包括wxml,wxss,js,json。其中wxml对应html界面,wxss对应css界面,json文件不是必选的,但一般可以全部创建出来。

3.2 关于JSON配置

JSON配置大致上可以分为两种。一种是页面page的JSON配置,另一种是全局app的JSON配置。

3.2.1 app.json文件

App.json文件存在于项目的根目录下,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab。
有5项配置,分别是:pages、windows、tabBar、networkTimeout、debug.
Pages: 用于配置页面路径信息。接受一个字符串数组,每一项都对应页面(路径+文件名)信息,数组的第一项作为首页进行访问。小程序增减页面都需要对pages进行修改,否则会出现错误。文件名不需要写后缀wxml,wxss,js,json,因为框架会自动同一个路径下的4个文件。
例如: “/pages/example/example”,其中前面的/pages/example是作为路径,而后面的example就是page文件名,框架会自动加载/pages/example/下面的所有example,且后缀为wxml,wxss,js,json的文件。

Windows: 用于设置小程序的状态栏、导航条、标题、窗口背景色。

TabBar: 如果小程序是一个多 tab 应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。
tabBar 中的 list 是一个数组,只能配置最少2个、最多5个 tab,tab 按数组的顺序排序。
如果你需要动态设置tabBar的路径信息,那么这个将无法满足需求,这个配置在app.json文件中,无法快捷的在程序执行期间进行切换

3.2.2 page.json文件

每一个小程序页面也可以使用.json文件来对本页面的窗口表现进行配置。 页面的配置比app.json全局配置简单得多,只是设置 app.json 中的 window 配置项的内容,页面中配置项会覆盖 app.json 的 window 中相同的配置项。 页面的.json只能设置 window 相关的配置项,以决定本页面的窗口表现。
如果页面中需要加载自定义组件那么将会使用到一个属性usingComponents属性。这个将在后面的自定义组件中讲到。

3.3 API开发

3.3.1 蓝牙开发

3.3.1.1 概述

因为写过关于蓝牙智能家居的项目,所以会将重点放在这里。
蓝牙智能家居连接的业务逻辑如下,

  • 初始化蓝牙设备
  • 打开蓝牙搜索服务
  • 搜索蓝牙列表
  • 连接设备
  • 查找、匹配服务
  • 查找、匹配特征
  • 打开订阅
  • 请求握手,写入设备
  • 监听设备返回信息进行处理
3.3.1.2 使用方法
  1. 从git上下载开发库GIT地址
  2. BleTool.jsTool.js放入在小程序项目下的lib文件(否则需要修改成自己的文件路径)
  3. 在App.js文件中引入BleTool.js文件
const BLEManage = require('lib/BleTool.js')
  1. 在App.js文件中onLaunch初始化蓝牙库
this.globalData.bleManage = new BLEManage(this)
  1. 使用方法:
获取设备列表:
    this.globalData.bleManage.getDeviceList([搜索次数],[搜索间隔],[回调方法])
查找并连接设备:
    this.globalData.bleManage.getDevices([设备MAC],[回调方法],[监听响应参数])
3.3.1.3 注意事项
  1. 因为最好不用一直保持蓝牙设备在线,所以需要监听蓝牙连接状态,但可以根据需求选择。
  2. 最好将蓝牙的状态保存下来,将蓝牙类绑定到app.globaldata下面,方便全局 操控蓝牙。
  3. 当搜索到设备后,这时设备掉线,会出现无法连接到设备,但是从设备列表能看到设备的问题,需要重启适配器再搜索即可正常。
  4. 推出小程序的时候,最好将小程序的蓝牙状态保存,然后等切回小程序的时候,在进行断开重连,确保小程序在后台运行的时候,蓝牙的状态信息保持一致。否则会出现异常。
  5. IOS系统更新13.1以后,出现蓝牙需要开放授权。位置是:设置->隐私->蓝牙->对应的应用。
3.3.1.4 代码说明
  1. 首先,初始化需要保存的蓝牙状态,这个将用于获取和监听全局的蓝牙状态。
constructor() {
    let that = this;
    //记录自身,防止某些函数this指向问题
    that.self = this;
    //是否开启调试
    that.debug = false;
    //操作状态控制
    that.onlyOne = false; //唯一控制
    that.silent = false; //静默连接
    that.rootChangeStop = false; //路由修改是否停止
    that.canRun = false; //蓝牙库是否可以继续运行
    that.rootPage = null;

    //属性
    that.available = false;
    that.searchState = false;
    that.platform = null;
    that.connectState = false;
    //蓝牙搜索计时器
    that.getDeviceAllTime = 3;
    that.getDeviceTime = that.getDeviceAllTime;
    that.getDeviceTimeState = true;
    that.getDeviceTimeOut = null;
    that.getDeviceRSSICount = 0;
    that.getCanDevice = false;
    //蓝牙连接计时
    that.getConnectDeviceAllTime = 2;
    that.getConnectDeviceTime = that.getConnectDeviceAllTime;
    that.getConnectDeviceTimeState = true;
    that.connectId = null;
    //显示计时器
    that.showMentionTimer = null;

    that.listenAdapterStateChange();
    that.listenConnection();
    that.openBLEAdapter(function() {
      that.closeBeforeConnect();
    });

  1. 初始化了蓝牙对象的时候,打开适配器;适配器打开成功,则开启搜索服务;打开失败则,提示用户需要打开蓝牙。

listenAdapterStateChange 则是用来监听适配器的状态改变,如果用户关闭蓝牙,则方法会返回false ,这时我们就可以将蓝牙对象的openAdapter的状态标记为false,即未开启,这里的延时1s搜索是因为说是有些设备可能存在状态先响应然后再启动的现象,然后就无法搜索到设备了。

    
  /**
   * 打开蓝牙适配器
   */
  openBLEAdapter(callBack) {
    let that = this
    console.log("openBLEAdapter")
    wx.openBluetoothAdapter({
      success: function(res) {
        console.log('openBLEAdapter_success')
        that.checkAvailable({
          toast: true
        }, true)
        that.showMention("开启蓝牙成功", true);
        // setTimeout(function() {
        //   that.startSearchDevice(callBack);
        // }, 1000)
        callBack();
      },
      fail: function(res) {
        console.log('openBLEAdapter_fail', res)
        that.checkAvailable({
          toast: true
        }, false)
      }
    })
  }
  /**
   * 监听适配器状态
   */
  listenAdapterStateChange() {
    var that = this
    wx.onBluetoothAdapterStateChange(function(res) {
      console.log("listenAdapterStateChange", res)
      that.searchState = res.discovering
      let available = that.checkAvailable({
        toast: true
      }, res.available);
      if (!res.available) {
        that.onlyOne = false; //唯一控制
        that.silent = false; //静默连接
        that.rootChangeStop = false; //路由修改是否停止
      }
      // if (res.available) {
      //   // if (!that.available) {
      //   that.available = res.available
      //   // that.startSearchDevice();
      //   // }
      // } else {
      //   that.available = res.available
      //   console.log("请打开蓝牙2")
      //   that.showMention('请打开蓝牙2', true)
      // }
    })
  }

  /**
   * 开始搜索
   */
  startSearchDevice(callBack) {
    let that = this;
    console.log("startSearchDevice")
    if (that.checkAvailable({})) {
      if (!that.searchState) {
        // if (that.platform == "ios") {
        console.log("延时1s搜索")
        that.showMention('准备搜索设备', true, 1)
        setTimeout(function() {
          that.wechatSearchDevice(callBack);
        }, 1000)
        // } else {
        // console.log("立即搜索")
        // that.wechatSearchDevice();
        // }
      }
    } else {
      that.showMention("请打开蓝牙", true);
    }
  }

  /**
   * 开始搜索微信方法
   */
  wechatSearchDevice(callBack) {
    let that = this;
    wx.startBluetoothDevicesDiscovery({
      // services: [MainService],
      success: function(res) {
        that.searchState = true;
        console.log("成功,准备开始搜索: ")
        console.log(res)
        that.showMention('开始搜索设备', true)
        if (callBack != undefined) {
          callBack();
        }
      },
      fail: function(res) {
        that.available = false
        that.searchState = false;
        console.log("开启搜索失败: ")
        that.showToast({
          title: '开启搜索失败',
        })
      }
    })
  }

  1. 搜索蓝牙设备的2种方式

开始搜索蓝牙设备了,如果你需要从周围可能存在的蓝牙设备中,选取你想要的,那么你可以在蓝牙设备的名字上动动手脚了。比如,你可加上前缀FFFF-这样的。然后 判断获取到的名字是否包含FFFF-前缀,有就加入到显示列表里面。

    
  //微信获取设备列表
  getDeviceList(count, time, callBack) {
    let that = this;
    that.searchCount = count;
    // that.searchState = true;
    if (that.searchInterval != null) {
      clearInterval(that.searchInterval);
      that.searchInterval = null;
    }
    that.searchInterval = setInterval(function() {
      if (that.checkRoutePageChange()) {
        return;
      }
      that.showMention("第" + (count - that.searchCount + 1) + "次搜索", false)
      if (that.searchCount > 0) {
        wx.getBluetoothDevices({
          success: function(res) {
            console.log(635, res)
          }
        })
        that.searchCount--;
        return;
      } else {
        that.showMention("搜索成功", true, 2)
        clearInterval(that.searchInterval);
        wx.getBluetoothDevices({
          success: function(res) {
            console.log("getDeviceListSuccess", res)
            callBack(res.devices);
          }
        })
      }
    }, time * 1000)
  }

也许你有时候需要的是查找并连接指定的设备,那么你可以通过下面这样的形式


  /**
   * 获取设备
   */
  getDevices(mac, callBack, listenFun, options) {
    let that = this;
    console.log("getDevices", options)
    mac = mac.toLowerCase(); //转换小写

    if (!that.checkAvailable({
        toast: true
      })) {
      return;
    }

    //检查是否有蓝牙操作在运行
    if (that.checkOnlyOne({
        toast: true
      }, true)) {
      return;
    }

    //配置属性
    // that.onlyOne = true;
    console.log("typeof options", typeof options)
    if (typeof options == "object") {
      that.slient = options.slient || false;
      that.rootChangeStop = options.rootChangeStop || false;
    } else {
      that.slient = false;
      that.rootChangeStop = false;
    }

    that.callBack = function() {
      that.onlyOne = false;
      callBack()
    }
    that.listenFun = listenFun
    if (that.connectState && that.mac == mac) {
      that.callBack()
      return;
    }
    that.startSearchDevice();
    that.rootPage = getCurrentPages()[getCurrentPages().length - 1].route;
    that.showMention("开始搜索", true, 3)
    that.resetSearchDevice(mac);
  }


  1. 连接设备

蓝牙连接的过程就是不断根据与蓝牙设备所定好的一些协议,服务值,特征值等,主要是为了保证安全性。

  
  /**
   * 创建连接
   */
  connectDevice(msg) {
    let that = this;
    console.log("connectDevice")
    if (that.checkRoutePageChange()) {
      return;
    }
    msg = msg == undefined ? '连接中' : msg;
    that.showMention(msg, false)
    wx.createBLEConnection({
      deviceId: that.connectId,
      success: function(res) {
        console.log(res)
        console.log("连接成功")
        that.showMention('连接成功', true)
        that.connectState = true;
        that.searchService();
        console.log("保存", that.connectId);
        tool.storage.save("connectId", that.connectId)
      },
      fail: function(res) {
        console.log("miss", res)
        that.connectState = false;
        that.getConnectDeviceTime--;
        if (that.checkRoutePageChange()) {
          return;
        }
        if (!that.checkAvailable({})) {
          that.showMention("蓝牙关闭", true, 2)
        } else {
          if (that.getConnectDeviceTime > 0) {
            that.showMention("连接失败", false)
            setTimeout(function() {
              // that.connectDevice("第" + (that.getConnectDeviceAllTime - that.getConnectDeviceTime) + "次重连中");
              that.connectDevice("重连中");
            }, 1000);
          } else {
            that.showMention("重连失败", true, 2);
            wx.showModal({
              title: '温馨提示',
              content: '请确认设备正常通电,即将重启蓝牙适配器',
              success: function(res) {
                if (res.confirm) {
                  console.log('用户点击确定,开始重启重连')
                  that.restartBleAdapter(function() {
                    // that.getConnectDeviceTime = that.getConnectDeviceAllTime;
                    // that.connectDevice()
                    that.resetSearchDevice(that.mac)
                  })
                } else if (res.cancel) {
                  console.log('用户点击取消, 取消重启重连')
                }
              }
            })
          }
        }
      }
    })
  }


  /**
   * 搜索服务
   */
  searchService() {
    console.log("searchService")
    let that = this;
    that.showMention('数据处理中', true, 3)
    wx.getBLEDeviceServices({
      //服务uid
      deviceId: that.connectId,
      success: function(res) {
        console.log(res)
        for (let i = 0; i < res.services.length; i++) {
          let rs = res.services[i]
          if (rs.uuid.indexOf(MainService) > -1) {
            console.log('找到匹配服务', res.services[i].uuid)
            that.mainservice = res.services[i].uuid;
            that.characteristic()
            break;
          }
        }
      },
      fail: function() {
        wx.hideLoading();
        console.log("搜索服务失败");
        that.showToast({
          title: '搜索服务失败',
        })
      }
    })
  }

  /**
   * 特征值获取
   */
  characteristic() {
    console.log("characteristic")
    let that = this
    wx.getBLEDeviceCharacteristics({
      deviceId: that.connectId,
      serviceId: that.mainservice,
      success: function(res) {
        console.log("特征id:", res)
        for (let i = 0; i < res.characteristics.length; i++) { //写入的特征值
          let ct = res.characteristics[i]
          if (ct.uuid.indexOf(UpdateCharacteristic) > -1) {
            console.log('找到更新匹配特征', ct.uuid)
            that.updateuuid = ct.uuid;
            that.openNotify(ct.uuid);
          } else if (ct.uuid.indexOf(WriteCharacteristic) > -1) {
            console.log('找到写匹配特征', ct.uuid)
            that.writeuuid = ct.uuid;
          } else if (ct.uuid.indexOf(ReadCharacteristic) > -1) {
            console.log('找到读匹配特征', ct.uuid)
            that.readuuid = ct.uuid
          }
        }

        //连接成功后,不保持静默方式
        that.slient = false;
        // setTimeout(function() {
        that.callBack();
        // }, 1000)
      },
      fail: function(res) {
        console.log('找不到特征值')
        console.log(res);
        wx.hideLoading();
        that.showToast({
          title: '找不到特征值',
        })
      }
    })
  }


  /**
   * 打开订阅
   */
  openNotify(uuid) {
    var that = this
    console.log("openNotify")
    wx.notifyBLECharacteristicValueChange({
      deviceId: that.connectId,
      serviceId: that.mainservice,
      characteristicId: uuid,
      state: true,
      success: function(res) {
        console.log("notify打开成功", res)
        that.listenNotifyValueChange()
        // console.log()
        // wx.onBLECharacteristicValueChange(function (res) {
        //   console.log("订阅的值",res)
        // })
      },
      fail: function(res) {
        console.log("notify打开失败");
        console.log(res)
        wx.hideLoading();
        that.showToast({
          title: 'notify打开失败',
        })
      },
    })
  }
  1. 下面是关于一些基本的操作和监听
    
  /**
   * 写入数据
   */
  writeCharacteristicValue(str, func) {
    console.log("writeCharacteristicValue")
    let that = this;
    if (that.checkRoutePageChange()) {
      return;
    }
    // console.log(that.connectId, that.mainservice, that.writeuuid, str);
    if (!that.connectState) {
      tool.showMention("未连接设备")
      return;
    }
    func = func || function() {};

    let resObj = {}

    wx.writeBLECharacteristicValue({
      deviceId: that.connectId,
      serviceId: that.mainservice,
      characteristicId: that.writeuuid,
      value: tool.string2Buffer(str),
      success: function(res) {
        that.showToast({
          title: '写入成功',
        })
        console.log("writeDate-->", res);
        resObj.state = "success"
        func(resObj)
      },
      fail: function() {
        console.log("写入失败")
        resObj.state = "fail"
        func(resObj)
      }
    })
  }



  /**
   * 监听特征值
   */
  listenNotifyValueChange() {
    console.log("listenNotifyValueChange")
    var that = this
    console.log("监听特征变化")
    wx.onBLECharacteristicValueChange(function(res) {
      console.log("收到数据")
      // console.log('WriteDataType = ' + WriteDataType)
      let value = res.value
      console.log(value);
      let value2 = tool.uint8Array2Str(value)
      console.log("returnstr", value2)
      let dataView = new DataView(tool.string2Buffer(value2))
      that.listenFun(dataView);
      // return;
    })
  }
  /**
   * 监听连接状态
   */
  listenConnection() {
    let that = this;
    console.log("listenConnection")
    wx.onBLEConnectionStateChange(function(res) {
      console.log("connectState", res);
      that.connectState = res.connected;
      if (res.connected) {
        that.showToast({
          title: "连接成功",
        })
      } else {
        console.log(that.available, false)
        // if (that.available) {
        //   that.startSearchDevice()
        // }
        that.showToast({
          title: "连接断开",
        })
      }
    })
  }

  1. 一些基本的字符串和数组的转换操作
//Tool.js


/*
  16进制字符串转整形数组
*/
function str2Bytes(str) {
  var len = str.length;
  if (len % 2 != 0) {
    return null;
  }
  var hexA = new Array();
  for (var i = 0; i < len; i += 2) {
    var s = str.substr(i, 2);
    var v = parseInt(s, 16);
    hexA.push(v);
  }

  return hexA;
}

/*
  整形数组转buffer
*/
function array2Buffer(arr) {
  let buffer = new ArrayBuffer(arr.length)
  let dataView = new DataView(buffer)
  for (let i = 0; i < arr.length; i++) {
    dataView.setUint8(i, arr[i])
  }

  return buffer
}

/*
  16进制字符串转数组
*/
function string2Buffer(str) {
  let arr = str2Bytes(str);
  return array2Buffer(arr)
}

/*
  ArrayBuffer转十六进制字符串
*/
function uint8Array2Str(buffer) {
  var str = "";
  let dataView = new DataView(buffer)
  for (let i = 0; i < dataView.byteLength; i++) {
    var tmp = dataView.getUint8(i).toString(16)
    if (tmp.length == 1) {
      tmp = "0" + tmp
    }
    str += tmp
  }
  return str;
}


3.3.2 camera

在编写摄像机组件的时候,我发现了关于手机设备的兼容问题,拍照后返回的临时图片路径,将他显示到界面上,会出现明显的颜色变换,像是人会变阿凡达那样。问题没找出,因为大部分的机型不会有该问题,已在酷派手机上发现,可能是系统问题.


老规矩写的不清晰的地方,可以指出,我会不定时更新和修改。一起加油.

所有的伟大,都来自于一个勇敢的开始。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值