美文网首页
微信小程序初体验

微信小程序初体验

作者: Shermanon | 来源:发表于2017-07-04 11:53 被阅读244次

前言

家里书买了不少,但来不及看也不记得自已都有什么书了;另外有时想看一本书买了回来,才发现身边有人已经买过了,是可以借来看的。因此,一直想出一个个人书籍管理的工具,并能支持熟人间书籍借阅的功能。

微信小程序,在微信发布整整6年后的2017年1月9日发布,号称纯功能性、用完即走、低成本、高效率。因此,何不就着这平台体验一把。本文就开发一个个人书架管理的WX小程序的过程中,对遇到的折腾点、问题点和想法做个记录,以备参考。

1. 开发者工具

![Uploading gh_7ddb46850a7d_258_730288.jpg . . .]

先来说说开发者工具的使用,帮助提升编码效率。

(1)调试 - AppData

在调试面板的AppData页可以查看当前打开各页中Data的内容,这样就不用再为了查看变量而输出console.log了;对于数据缓存Storage也是同样的。


调试 - AppData
(2)真机本地调试

小程序访问远程后台是有https+备案域名的要求,但开发过程中是希望能避开这些限制,好在开发工具已经支持在开发环境下不校验请求域名、TLS版本以及HTTPS证书,将如下选项勾选即可:


开发环境不校验域名与HTTPS

同时,当然也希望能够在本地调试后台,那么由于开发环境可不校验域名,因此我采用让手机和开发机连同一个局域网,通过局域网ip访问即可做到真机的本地调试。当然,如果非要通过域名的话,则可以考虑用一些软件工具在本地虚一个域名出来。

(3)wx.request出现400的坑

提前提一点,如果在调用中出现如下错误:


400

则是由于请求的header的Content-type写法变了,需要配置为对应的type就好了

header:{
    "Content-Type":"json"
},

参考:微信小程序request出现400的坑

2. WX小程序前端

前端主要基于官方提供的微信开发者工具,采用类HTML+JS+CSS的方式进行开发,单个小程序应用大小不能超过10M。

(1)flex布局

实现可伸缩的布局方式,代码参考如下

.kind-list-item-hd {
  padding: 30rpx;
  display: flex;
  align-items: flex-start;
  transition: opacity .3s;

通过flex-direction属性还能控制布局方向。

  • row :从左到右的水平方向为主轴
  • row-reverse:从右到左的水平方向为主轴
  • column:从上到下的垂直方向为主轴
  • column-reverse从下到上的垂直方向为主轴

不过在并列的几个view中,想要最右的view靠右排列,而其他的依然靠左,则没有找到现成的配置属性;最后采用了扩展中间view的宽度的方式,将最右边的view“排挤”到最右侧以达到效果。

.kind-list-info {
  flex-direction:column;
  width: 63%;
}
(2)TabBar不能自动打开扫描功能

通过如下代码可以调用设备摄像头进行扫描,并在扫描成功success时将扫描结果导航到其他目标页面。

scanCode: function () {
    console.log('scanCode')
    wx.scanCode({
      success: function (res) {
        wx.navigateTo({
          url: '../scanner/scanner?result=' + res.result
        })
      },
      fail: function (res) {
      }
    })
  }

不过想要在tarbar中添加一个按钮,实现点击后直接打开摄像头,通过在tarbar对应的path页面中注册onLoad函数,并在onLoad添加以上代码,发现在设备中并没有生效(不过在开发工具中使用到时打开了文件对话框),因此最后改用按钮的方式来实现了。

(3)网络通信

通信方式如下四种,一类是消息通信,一类是文件通信。+ https请求:

  • wx.request(object)
  • 文件上传:wx.uploadFile(object)
  • 文件下载:wx.downloadFile(object)
  • WebSocket:wx.connectSocket(object)等

其中,消息通信分为短连接的https请求和可实现长连接的WebSocket通信,WebSocket通信还可实现服务器端向客户端推送的能力,因此具体实现根据应用场景来选择。

(4)API执行fail时获取错误信息

wx.navigateTo有一个约束,就是不能导航到TabBar的页面,否则会抛错,错误信息可以再fail中捕获到,并通过error来查看。

wx.navigateTo({
      url: '../scanner/scanner?result=123',
      success: function () {
        console.log('scanCode success')
      },
      fail: function (error) {
        console.log(error)
      }
})
(5)切换Tab页时的数据传输

如上所说,切换的页面是TabBar时,需要使用wx.switchTab,该api不能带数据参数,因此若要解决其他页面切换到Tab页并实现数据更新,有如下两种思路:

此次使用的是全局变量globalData的方式,通过每次Tab页显示时会调用的onShow函数来加载更新后的全局变量,参考代码如下:

onShow: function() {
    console.log('onShow')
    var that = this
    that.setData({
      bookListSize: app.globalData.bookListSize,
      bookList: app.globalData.bookList
    })
  }
(6)引用weui效果不一致的问题

参考https://weui.io/ 来引用weui的一些效果,若原样照搬html版的会发现效果不一致,在小程序示例工程中带的weui包(/page/common/lib/weui.wxss)中的效果还是不一致,有的样式被拆开了,需要注意。例如之前在微信公众平台开发者社区提的一个问题:关于WEUI(loadmore)的效果不一致的问题

weui.css
.weui-loadmore_line .weui-loadmore__tips {
  position: relative;
  top: -0.9em;
  padding: 0 .55em;
  background-color: #FFFFFF;
  color: #999999;
}
/* 到小程序中变成这样了 */
weui.wxss
.weui-loadmore__tips_in-line {
  position: relative;
  top: -0.9em;
  padding: 0 .55em;
  background-color: #FFFFFF;
  color: #999999;
}
(7)修改输入框placeholder文字的样式

input有个placeholder-class属性,可以自定义样式

<input   placeholder-class="psection" maxlength="10" placeholder="最大输入长度10" />
.psection{
    color: #FFC0CB;
}

参考:http://www.henkuai.com/forum.php?mod=viewthread&tid=15684

(8)搜索功能

收藏的书多了,必然少不了搜索。观察其他app或小程序的实现方式,会发现一般在主页置一个输入框;当点击输入框时,会跳转到单独的搜索页面,通过该页面可以提供热门搜索、搜索记录、分类搜索等更多功能,这样不影响原主页的处理。

首页搜索框,摆摆样子
这里的引入了wxSearch组件,其已经实现了自定义热门搜索、搜索历史、搜索建议的功能。在这基础之上,配套调整了CSS样式,根据需要目前只取了搜索历史功能(热门搜索词的选择有待算法研究),优化搜索历史框消失、重现的流程,添加对弹出的虚拟键盘点击搜索键的监听处理,并添加了清空搜索按钮功能。
点击首页搜索框后跳转搜索页
添加清空搜索框
(9)意见反馈

任何一个应用收集用户的反馈信息或与用户互动是十分重要的。
一般有两种方式:

  • 在线客服:微信小程序提供了客服消息的支持,只要添加如下代码即可;点击对话图标即可进入客服对话框
  /**
   * 用户点击右上角分享
   */
  <view class="weui-cells weui-cells_after-title">
    <view class="weui-cell weui-cell_switch">
      <view class="weui-cell__bd">在线客服</view>
      <contact-button size="40" session-from="custService"></contact-button>
    </view>
  </view>
在线客服
在这基础之上,还可以接入一些第三方智能客服、智能机器人,笔者在此尝试了V5智能客服,以下这些对话都是V5机器人自动回答的哦~
智能机器人小厉
  • 在线留言(表单):这种方式类似于离线提交表单,有一些现成的平台能够提供功能(比如金数据),不过由于小程序目前(2017.6)还不支持外部链接,所以没有办法引用,后续期待小程序能支持外链,或者自己来实现吧。
    金数据表单效果图

3. WX小程序后端

后端服务基于NodeJS+MySql来实现。一开始为方便结构扩展,数据库拟用Mongo,但Mongo的云数据库相比关系数据库太贵,所以还是选择了MySql。

PS:附当前最新的5.7.18版本ZIP包在Windows环境下的安装过程参考:http://www.jb51.net/article/112661.htm

(1)Node的日志输出

日志框架有多种,看到提的比较多的有三种:

这里采用Log4JS就足够了,配置参考:

{
  "appenders": [{
    "type":"clustered",
    "category": "app",
    "appenders": [
      {
        "type": "console"
      },
      {
        "type": "dateFile",
        "filename": "./log//app.log",
        "pattern": "-yyyy-MM-dd",
        "alwaysIncludePattern": true
      }
    ],
    "replaceConsole": true
  }]
}
var log4js = require('log4js')
var log = log4js.getLogger('app');
(2)严格模式

JS中有一种写法是'use strict';,这个表示严格模式,简单介绍一下,严格模式的目的是:

  • 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;
  • 消除代码运行的一些不安全之处,保证代码运行的安全;
  • 提高编译器效率,增加运行速度;
  • 为未来新版本的Javascript做好铺垫。

而由此带来的影响请注意:

  • 如果在语法检测时发现语法问题,则整个代码块失效,并导致一个语法异常。
  • 如果在运行期出现了违反严格模式的代码,则抛出执行异常。

参考:Javascript 严格模式详解使用严格模式有什么优点

(2)Node进程守护

Node进程管理用pm2,防止未捕捉的异常中断程序没起来。

pm2 start ibookshelf.json
# ibookshelf.json
{
    "name": "ibookshelf",
    "script": "app.js",
    "cwd": "./",
    "exec_mode": "fork",
    "watch": false,
    "env": {
        "NODE_ENV": "production",
        "DEBUG_SDK": "yes"
    }
}

不过要注意的是watch配置用来监听文件是否变化,若变化则自动重启。那如果把日志文件也生成在了工程目录下,则文件在不停的打日志,应用就会不停的重启了。。这时可以考虑把日志外迁至独立的目录,或者使用ignore_watch参数,配置参考:PM2实用入门指南

4. 数据库(MySql / Mongodb)

(1)MySQL中TIMESTAMP与DATETIME的区别
  • TIMESTAMP把客户端插入的时间从当前时区转化为UTC(世界标准时间)进行存储;查询时将其又转化为客户端当前时区进行返回,这也就意味着查询的结果会和机器时区设置有关。
  • DATETIME不做任何改变,原样输入输出。
    另外,从mysql5.6开始,DATETIME也支持设置默认值和更新了。
CREATE TABLE `test` (
  `id` int(11),
  `meta_updateAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)```
参考:[MySQL5.6时间类型timestamp和datetime有了重大改变](http://www.linuxidc.com/Linux/2012-09/71430.htm)

######(2)Mongoose插入数据库时的命名问题
首先在创建数据库连接时需指定库名,否则会默认连接test库
```JavaScript
mongoose.connect("mongodb://localhost:27017/数据库库名");

另一个命名问题是关于集合的,在定义model时,如果不通过如下方式定义集合名时,mongoose默认采用model名,并且判断model名是否可数,若可数的话会采用module名+‘s’的方式(如userinfos)

var UserInfo = mongoose.model('UserInfo', UserInfoSchema, '集合名');

参考:Mongoose在向集合中插入文档时的集合命名问题

5. 其他

(1)JS日期格式化转换方法

引入moment.js:http://momentjs.cn/

npm install moment
var moment = require('moment');
moment('2017-06-08T00:24:07.231Z').format('YYYY-MM-DD'); //2017-06-08

之前还使用了另一种方式,对Date原型添加如下方法:

Date.prototype.format = function(fmt) { 
     var o = { 
        "M+" : this.getMonth()+1,                 //月份 
        "d+" : this.getDate(),                    //日 
        "h+" : this.getHours(),                   //小时 
        "m+" : this.getMinutes(),                 //分 
        "s+" : this.getSeconds(),                 //秒 
        "q+" : Math.floor((this.getMonth()+3)/3), //季度 
        "S"  : this.getMilliseconds()             //毫秒 
    }; 
    if(/(y+)/.test(fmt)) {
            fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); 
    }
     for(var k in o) {
        if(new RegExp("("+ k +")").test(fmt)){
             fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));
         }
     }
    return fmt; 
}        

然后就可以这样调用了:

var time1 = new Date().format("yyyy-MM-dd hh:mm:ss");
var time2 = new Date().format("yyyy-MM-dd");

参考:http://www.cnblogs.com/tugenhua0707/p/3776808.html
此外,发现在NodeJS中写入new Date()或Date.now()的时间都是格林威治时间,比北京时间慢8小时,而原有设置时区的方式(process.env.TZ = "Asia/Shanghai";)不可用,因此改用如下方式:

process.env.TZ = "Asia/Shanghai";
Date.prototype.TimeZone = new Map([
    ['Europe/London',0],
    ['Asia/Shanghai',+8],
    ['America/New_York',-5]
    ])
Date.prototype.zoneDate = function(){
    if(process.env.TZ == undefined){
        return new Date();
    }else{
        for (let item of this.TimeZone.entries()) {
            if(item[0] == process.env.TZ){
                let d = new Date();
                d.setHours(d.getHours()+item[1]);
                return d;
            }
        }
        return new Date();
    }
}

然后这样调用就可以获取当前时间了:

new Date().zoneDate()
(2)JS异步批量请求时,保持返回数据顺序和请求的顺序一致

比如收到一组按收藏时间排序的ISBN码,然后通过ISBN查询图书信息,将收到的图书信息存储在数组中并保持和ISBN的顺序一致;但由于是通过JS异步并发发起http请求,因此收到图书信息的顺序并不一致。
对这种情况拟两种解决方式:

  • 提前生成一个数组,将ISBN作为KEY按顺序放好了,待图书信息返回时,放到对应的位置即可,直至所有信息返回
  • 收到所有数据后,再按照一定规则进行排序处理(例如按照收藏时间、或匹配ISBN顺序)
  • 将异步操作改为同步(如Promise,参考:http://blog.csdn.net/qq_31383345/article/details/60574200

第一种方式相对更简单,且未放弃异步相对于同步的优势,因此在这里采用了第一种方式。

后记

由此,基本完成一个简单的小程序功能,该小程序叫“厉害了我的书”,现已发布,欢迎微信扫码体验。小程序发展非常迅速,新增功能和特性都很频繁,WX小编经常大半夜推送新功能信息,令人振奋。

后续将在此基础上不断扩充功能,有新的坑点、亮点和想法笔者也会有新的记录和发布 (ง •_•)ง

厉害了我的书小程序

相关文章

网友评论

      本文标题:微信小程序初体验

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