这可能是一个java程序员最不务正业的一次分享了。

小程序的火热相信不用我多说了,年初的时候老婆去浦东某达面试,甚至都被问有没有小程序测试经验。俨然小程序成为了互联网公司自PC,WAP,安卓,IOS之后又一不可或缺的入口。正好这段时间公司也在做一款小程序,于是顺便也学习了一把。当然因为我是一个后端猿,自然是以后端的视角来谈谈,肯定和前端的同学还是比不上的。

学习小程序,我认为对于后端同学还是比较有优势的,因为后端同学对于HTML,CSS以及JS这些前端基本知识还是有所涉猎的,而前端的同学对于后端可能就没那么了解了。接下来,以我的实践经历来简单聊一聊小程序,算是总结也算是个分享。

小程序用来做什么?

“触手可及”,“用完即走”。感觉这两个词把小程序的特点描述的真的是淋漓尽致。以微信的用户量,小程序免去了用户还需安装APP的繁琐。而且用完之后,无需刻意退出,直接离开即可,当下次某个时间点在想起来,重新翻出来就行了。这对很多行业来说可能是颠覆性的。以我个人的观点来看,小程序适合做一些业务简单,性能要求不高,使用频率相对较低的应用。比如像垂直电商行业就是典型的受益者,自媒体电商,生鲜电商,如果让用户去下载一个这样的APP成本是很大的,而使用小程序确悄然的避免了拉新客的难题。又比如我自己,如果我把自己的博客做成了一个APP,相信几乎不会有同学去下载,而使用小程序却偶尔还会有些同学会点进来看看的,哈哈。

入门小程序

首先开发小程序,需要一个专门的工具【微信开发者工具】,这个大家可以直接到微信公众平台下载。

接下来我们首先新建个快速启动模板看一下,如果你有注册账号有appid的可以填入,没有的话也没关系。点击图中小程序即可使用测试账号。

如上图,进入后即可看到这些文件。

可以说一个简单的小程序只有这些了。

  • app.js 主要是全局公共的js方法声明及调用所在的文件
  • app.json 是小程序全局的配置文件,所以有的页面都在要此注册,不然不允许访问
  • app.wxss 是小程序全局的css文件
  • pages下是对应着所有页面,每个页面,可以添加四种类型的文件,.json,.wxss,.wxml,.js

另外在说下这四种类型的文件,小程序pages下面基本上每个文件夹相当于一个页面,每个文件夹下面有四种命名相同但类型不同的文件,这四种构成了页面的全部。

  • .json 后缀的 JSON 配置文件
  • .wxml 后缀的 WXML 模板文件,类似web开发的html
  • .wxss 后缀的 WXSS 样式文件,类似web开发的css
  • .js 后缀的 JS 脚本逻辑文件,它就是一个js啊,不过小程序的js不能操作dom,是基于数据绑定的哦

然后我们在看下js文件的构成,注释很清晰:

  1. Page({
  2.  
  3. /**
  4. * 页面的初始数据
  5. */
  6. data: {
  7.  
  8. },
  9.  
  10. /**
  11. * 生命周期函数--监听页面加载
  12. */
  13. onLoad: function (options) {
  14.  
  15. },
  16.  
  17. /**
  18. * 生命周期函数--监听页面初次渲染完成
  19. */
  20. onReady: function () {
  21.  
  22. },
  23.  
  24. /**
  25. * 生命周期函数--监听页面显示
  26. */
  27. onShow: function () {
  28.  
  29. },
  30.  
  31. /**
  32. * 生命周期函数--监听页面隐藏
  33. */
  34. onHide: function () {
  35.  
  36. },
  37.  
  38. /**
  39. * 生命周期函数--监听页面卸载
  40. */
  41. onUnload: function () {
  42.  
  43. },
  44.  
  45. /**
  46. * 页面相关事件处理函数--监听用户下拉动作
  47. */
  48. onPullDownRefresh: function () {
  49.  
  50. },
  51.  
  52. /**
  53. * 页面上拉触底事件的处理函数
  54. */
  55. onReachBottom: function () {
  56.  
  57. },
  58.  
  59. /**
  60. * 用户点击右上角分享
  61. */
  62. onShareAppMessage: function () {
  63.  
  64. }
  65. })

了解了这些基本上小程序开发就没问题了,其他就剩翻文档了。这里我建议把文档当成字典来读,读完简易教程和框架后,其他需要什么来查什么就行了,没必要像教科书一样一字不落的全看完。

因为微信开发者工具还比较初始,之前每建一个页面,我都是先建一个文件夹,然后在分别把四个文件建好。这里我介绍个小技巧,大家可以首先将要新建的页面注册进app.json,这时候工具会自动把文件夹和四种文件给你建好。说实话很奇怪,这种方法在官方文档上我并没有看到,不知道是我眼花还是官方真的没有写。

  1. {
  2. "pages":[
  3. "pages/index/index",
  4. "pages/logs/logs"
  5. ],
  6. "window":{
  7. "backgroundTextStyle":"light",
  8. "navigationBarBackgroundColor": "#fff",
  9. "navigationBarTitleText": "WeChat",
  10. "navigationBarTextStyle":"black"
  11. }
  12. }

再说下页面的注册,当我们在app.json文件中注册的时候,【pages/index/index】会将该页面下index.xx的四种文件加载进来,而不必一个个写了。还有就是文件夹名字和文件名是可以不同的,比如【pages/index/launch】会将index文件夹下所有的launch文件加载。但是建议还是一样把,不然看着挺别扭的。

最后在多说句,小程序的域名白名单问题,我发现很多同学不知道,包括身边的同事,一直还在用内网穿透来开发。

首先小程序对应用请求的域名是有限制的。

  1. 请求的域名必须在后台配置,非配置域名无法请求成功。
  2. 域名协议必须是https的,如果是http请求也是会失败的

当然,这是对线上版本来说。如果是我们本地开发,小程序提供了一个很人性化的功能。可以忽略这个限制,甚至你可以直接请求本地的IP地址+端口号,而不必使用繁琐的内网穿透的方式了。

具体操作方式就是在微信开发者工具中,点击【设置】-【项目设置】-【勾选】不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书 即可,如下图

下面就结合我的实践小程序来简单聊一聊,更多的资料大家可以查阅文档

开源实践

恰巧前段时间做了个练手的yyblog的开源项目,这次就拿这个项目做个简单的小程序客户端了。还是惯例,大家先看下效果图吧。

单纯的html,css,js实现,没有应用任何前端框架,还是比较适合参考学习的。ppps:反正我是不会说因为我不会才不用的 呜呜~~~流下了没有技术的泪水┭┮﹏┭┮。

微信小程序总的来说虽然已经上线那么久,但和传统意义上的开发语言上比,还不是那么稳定的,官方也在不断的调整中。

相信很多同学有遇到过这样的场景,当你第一次进入一个小程序的时候,会弹出来一个用户信息授权的弹窗。刚开始我写的时候也是这样处理的,但是后来在上传代码的时候看到,微信在9月12号的时候发了一个公告。

主要是取消了分享监听接口的回调,将获取用户信息的getUserInfo接口改为只有用户点击了相关授权组件才能触发,还有就是openSetting接口也改为了点击才能触发。所以做微信小程序开发还是要做关注下官方的动态,以免做好的功能确不能正常使用的尴尬。

全局配置

前面有说app.xx的相关文件,是小程序的全局配置文件,这里在单独说下app.js这个文件。当我们某些参数是全局需要的时候,我们就可以将相关的参数写在这个文件里面,比如我们请求的基础url,亦或是用户信息,用户ID这种请求必须携带的参数。同时我们可以将版本校验的代码写在这里,这里在多说一句,微信是支持版本校验的,当有新的版本代码的时候,可以做用户更新提示,这里不再需要我们后台校验,还是比较方便的。相关的代码如下:

  1. App({
  2.  
  3. onLaunch() {
  4. this.checkUpdate();
  5. },
  6.  
  7. globalData: {
  8. userInfo: {},
  9. apiBase: "https://www.laoyeye.net",
  10. userId: ""
  11. },
  12.  
  13. checkUpdate() {
  14. const updateManager = wx.getUpdateManager();
  15. updateManager.onCheckForUpdate(function (res) {
  16. // 请求完新版本信息的回调
  17. console.log(res.hasUpdate)
  18. })
  19. updateManager.onUpdateReady(function () {
  20. wx.showModal({
  21. title: '更新提示',
  22. content: '新版本已经准备好,是否重启应用?',
  23. success: function (res) {
  24. if (res.confirm) {
  25. // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
  26. updateManager.applyUpdate()
  27. }
  28. }
  29. })
  30. })
  31.  
  32. updateManager.onUpdateFailed(function () {
  33. // 新版本下载失败
  34. console.log('更新失败!')
  35. })
  36. }
  37. })

启动页

用户在刚开始进入小程序的时候,首先会展现一个启动页。起初我也不是这样设计的,基本上是用户进入后直接进入主页,弹出用户授权就行了,但是因为9.12的调整,也不得不作出了修改。让用户首先进入启动页授权,授权后跳转到主页。已授权的用户就把授权按钮隐藏,然后在等待1.5s后跳转到主页。这个过程中我除了做了获取用户授权的操作之外,还请求后台服务器在后台创建了用户数据,最终将userId返回到小程序。以后用户做评论,点赞,收藏等操作,均会携带userId,方便区分具体的用户。

这个页面其实有两个比较重要的知识要点,这里特别强调下。

首先,我们需要获取每个用户对于当前应用的openId,以便下次用户访问时,避免再次授权的重复操作。

调用wx.login()接口获取登录凭证(code)进而换取用户登录态信息,包括用户的唯一标识(openid) 及本次登录的 会话密钥(session_key)等。但是需要注意的是,用code去换取openid的操作,需要在服务端后台来做,如果在小程序js上交换,在开发版本你会看到也是可以正常获取登录,但是到生产上就不行了,因为小程序的安全限制,官方的域名是无法设置到白名单里。

代码如下:

  1. login(auth) {
  2. let that = this;
  3. //调用微信登录接口
  4. wx.login({
  5. success: function(res) {
  6. wx.request({
  7. url: app.globalData.apiBase + '/api/wx/login?code=' + res.code + '&nickname=' + app.globalData.userInfo.nickName +
  8. '&avatar=' + app.globalData.userInfo.avatarUrl,
  9. header: {
  10. 'content-type': 'application/json'
  11. },
  12. success: function(res) {
  13. //userId
  14. if (res.data.code == 200) {
  15. app.globalData.userId = res.data.data;
  16. console.log('获取用户信息=' + res.data.data);
  17. if (auth == 'auth') {
  18. that.direct();
  19. } else {
  20. let timer = setTimeout(() => {
  21. clearTimeout(timer)
  22. that.direct()
  23. }, 1500)
  24. }
  25. }
  26. }
  27. })
  28. }
  29. })
  30. },

第二,就是getUserInfo这个接口了,因为新规定的限制,以往如果用户没有授权,是会弹出授权的弹窗的。但是新规定之后如果你调用这个接口是在用户没有授权的情况下,那么会直接进入fail失败的回调的。所以你必须通过组件获取用户的授权,然后在用户点击的回调里在调用这个方法。

代码如下:

  1. <button class="show-btn" wx:if="{{userInfo.length == 0}}" type="primary" open-type="getUserInfo" bindgetuserinfo="onGetUserInfo"> 授权登录 </button>
  1. onGetUserInfo() {
  2. var that = this;
  3. wx.getSetting({
  4. success: function(res) {
  5. if (res.authSetting['scope.userInfo']) {
  6. wx.getUserInfo({
  7. success: function(res) {
  8. app.globalData.userInfo = res.userInfo;
  9. that.login('auth');
  10. },
  11. fail: function() {
  12. console.log('系统错误')
  13. }
  14. })
  15. } else {
  16. wx.showToast({
  17. title: "授权失败",
  18. duration: 1000,
  19. icon: "none"
  20. })
  21. }
  22. },
  23. fail: function() {
  24. console.log('获取用户信息失败');
  25. }
  26. })
  27. },

最后,这里在讲个小问题,我不知道是不是我个人的问题,我在做页面数据赋值的时候,会使用

this.data.requestUrl = requestUrl;
或者

this.setData({
postList: totalData
});

的方法。如果是异步情况下,必须使用方法二,页面上才能取到数据。但是有些情况下非异步方法里使用方法一数据竟然取不出来,可是我在断点中明明看到数据是赋值成功的啊。而这个时候换成方法二却又成功了。真的是不明所以,大家尽量使用方法二吧。

主页、技术页

把这两个页面一起讲,原因就是两个页面虽然展现形式上不同,但是技术特点上还是想同的。唯一的区别,可能就是后期我会把两个页面的数据接口做个调整,请求不同的数据了。

这个页面主要是两个知识点,上拉加载更多和下拉刷新了。

首先是上滑加载更多数据,这个其实是小程序官方提供的一个onReachBottom的方法,只要用户上滑到一定距离就会触发,这里我做了分页的处理。首次进入展示五条数据,当触发事件后请求第二页的数据。当然请求到第二页的数据并不能覆盖之前的数据哦,不然当用户在下滑时,刚才的数据没了,是不符合用户习惯的。

上滑事件触发的距离也是可以通过onReachBottomDistance实现的,默认50px

具体实现的代码如下:

  1. // 上滑加载更多数据
  2. onReachBottom: function (event) {
  3. var nextUrl = this.data.requestUrl +
  4. "?page=" + this.data.page + "&limit=5";
  5. util.ajax(nextUrl, "get", null, this.processData)
  6. wx.showNavigationBarLoading()
  7. },
  1. processData: function (indexData) {
  2. var totalData = {};
  3. //如果要绑定新加载的数据,那么需要同旧有的数据合并在一起
  4. if (!this.data.isEmpty) {
  5. totalData = this.data.postList.concat(indexData);
  6. }
  7. else {
  8. totalData = indexData;
  9. this.data.isEmpty = false;
  10. }
  11. this.setData({
  12. postList: totalData
  13. });
  14.  
  15. this.data.page += 1;
  16. wx.hideNavigationBarLoading();
  17. wx.stopPullDownRefresh();
  18. },

然后是下拉刷新,下拉刷新默认是不开启的,需要我们在*.json配置中通过enablePullDownRefresh属性开启,默认为false。

如果在app.json中设置为全局开启下拉刷新,在具体页面中即为当前页面开启。

相关代码如下:

  1. {
  2. "navigationBarTitleText":"小卖铺的老爷爷",
  3. "enablePullDownRefresh": true
  4. }
  1. onPullDownRefresh: function (event) {
  2. var refreshUrl = this.data.requestUrl +
  3. "?page=0&limit=5";
  4. this.data.techList = {};
  5. this.data.isEmpty = true;
  6. this.data.page = 1;
  7. util.ajax(refreshUrl, "get", null, this.processData);
  8. wx.showNavigationBarLoading();
  9. },

其实这两种方法,在大家看官方文档全局配置的时候就会看到的。上面我也有说过学习小程序,官方文档的简易教程和框架还是必看的,其他的就没那么重要了。

详情页

详情页其实就一个要讲,富文本的解析。

因为微信小程序并不支持html语言,所以需要转换为微信支持的wxml。

总的来说微信对富文本的支持并不好,官方也没什么好用的富文本解析组件。这次我使用的是github上关注度最高的小程序富文本组件wxParse ,虽说相对比较完善了,BUG还是不少的,而且作者好像也不维护了。但是目前实在没有找到其他什么好的替代方案,只能用这个了。如果大家还有其他组件,可以告诉我一下哈。

wxParse 的使用,项目上已经讲的很清楚了,大家方便可以移步:https://github.com/icindy/wxParse 查看。

我这边对wxParse做了一些小改动,主要解决部分手机报错无法解析的问题。原因是微信小程序不支持console.dir()的写法,这个小程序官方也有在社区说明。

分享

当你在页面的js文件中,定义了onShareAppMessage函数,这时候页面便拥有了分享功能,可以转发给微信好友。

  1. /**
  2. * 用户点击右上角分享
  3. */
  4. onShareAppMessage: function () {
  5. return {
  6. title: this.data.postData.title,
  7. path: '/pages/post-detail/post-detail?id=' + this.data.id + "&title=" + '小卖铺的老爷爷' + "&share=1"
  8. }
  9. },

如上,是我的分享代码,设置了分享的标题,以及跳转的路径等。这里我对路径做了参数处理,以便我能区分出用户的来源。为什么要区分用户来源呢,因为小程序的分享页面进入后有个很奇怪的问题,没有返回主页的按钮。所以我这边单独做了区分,当用户来自分享时,显示一个悬浮的返回首页的图标。

相关代码如下:

  1. <!-- 回到首页(分享的时候显示) -->
  2. <image wx:if="{{share}}" bindtap='onBackHome' class='back-home' src='/images/icon/home-page.png' lazy-load></image>
  1. /**
  2. * 回到首页(分享的时候)
  3. */
  4. onBackHome: function () {
  5. wx.reLaunch({
  6. url: '/pages/launch/launch?share=1"'
  7. })
  8. }

我的

最后在说说我的这个页面,其实这个页面没啥重要的东西。只是静态页面的跳转。

个人信息后期我会做成可绑定PC端账户的形式。

我的收藏是已经实现过的,只是可能详情页还没有具体收藏的入口,后期我会加上。具体的效果图如下。

还有一个就是打赏赞助这个页面,刚开始是准备做成小程序间关联,使用给赞api的接入方式。但是最近小程序官方对多个小程序间的跳转也要增加限制,就懒得弄了。

直接做了个详情页的跳转,详情页面贴了张赞赏码完事。需要注意的是小程序页面并不支持直接长按扫描哦,需要点击下图片,在弹出的图片上在长按识别图中的二维码。

效果如下图:

令我意外的是,虽然我的小程序上线没多久,但是竟然收到了两笔赞赏,真的是意外之喜。虽然不多,但是还是很感谢两位同学的支持。

ppps:写完文章后才想起来这个页面忘记说一个东西。小程序是可以使用阿里icon库的,具体使用方法大家网上看看吧。不说了,有兴趣的也可以看下我源码中的实现。

最后的最后

附上小程序微信预览地址:

之前有说这个项目是基于我前面的开源项目yyblog来写的,所以项目的PC端是已经完成的。所有请求的接口均已在yyblog实现。

小程序的源码也已在yyblog中上传,具体地址在:https://github.com/allanzhuo/yyblog/tree/master/yymini

如果本文对您有帮助,或者项目能对您有所启发的话,希望帮忙给yyblog项目点个Star吧,https://github.com/allanzhuo/yyblog

篇幅有限,写得有点长了,就到这里吧。总的来说技术难度不大,但是小坑还是比较多的。如果您有什么想法欢迎在评论中与我交流,码字不易,记得帮忙点个Star哦~

初尝微信小程序开发与实践的更多相关文章

  1. 初尝微信小程序2-基本框架

    基本框架: .wxml :页面骨架 .wxss :页面样式 .js :页面逻辑    描述一些行为 .json :页面配置 创建一个小程序之后,app.js,app.json,app.wxss是必须的 ...

  2. 初尝微信小程序3-移动设备的分辨率与rpx

    屏幕尺寸就是实际的物理尺寸. 分辨率(pt),是逻辑分辨率,pt的大小只和屏幕尺寸有关,简单可以理解为长度和视觉单位. 分辨率(px),是物理分辨率,单位是像素点,和屏幕尺寸没有关系. 微信开发者工具 ...

  3. 初尝微信小程序1-特点

    微信小程序特点:1.不需要下载安装即可使用 2.用户用完即走,不用关心是否安装太多应用 3.应用将无处不在,随时可用 适合开发的小程序类型:1.简单的用完即走的应用 2.低频的应用 3.性能要求不高的 ...

  4. 初尝微信小程序2-Swiper组件、导航栏标题配置

    swiper 滑块视图容器. 很多网页的首页都会有一个滚动的图片模块,比如天猫超市首页,滚动着很多优惠活动的图片,用来介绍优惠内容,以及供用户点击快速跳转到相应页面. Swiper不仅可以滚动图片,也 ...

  5. 微信小程序开发实践

    目录 项目是否适合移植到小程序上? 概要介绍 实践得到的经验 规则 小程序不支持的 新特性 小窍门 会话管理 进阶 项目是否适合移植到小程序上? 小程序由于微信提供了一些组件,在微信中的一些体验确实不 ...

  6. 微信小程序开发入门与实践

    基础知识---- MINA 框架 为方便微信小程序开发,微信为小程序提供了 MINA 框架,这套框架集成了大量的原生组件以及 API.通过这套框架,我们可以方便快捷的完成相关的小程序开发工作. MIN ...

  7. 三言两语之微信小程序开发初体验(1)

    一.前情   直接切入主题,微信发布了小程序,前端开发者表示,如果不会微信小程序的开发感觉就跟不上时代了,先解答几个容易出现歧义的问题 小程序就叫小程序,不叫应用号,因为apple不准,哈哈 小程序是 ...

  8. $微信小程序开发实践点滴——接入Bmob后端云

    Bmob后端云官网:http://www.bmob.cn/ 微信公众平台官网:https://mp.weixin.qq.com/ 微信小程序官方开发文档:https://mp.weixin.qq.co ...

  9. 微信小程序开发学习资料

    作者:初雪链接:https://www.zhihu.com/question/50907897/answer/128494332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...

随机推荐

  1. mysql explain extended 查看 执行计划

    本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 本文以转移至本人的个人博客,请多多关注! 1. explain 可以查看 ...

  2. centos7(debian,manjora,freebsd)命令及安装mysql、git、gpg、gogs,安装docker,zsh,chrome

    最小安装: 1. 选择English 2. DATE & TIME 修改好本地时间 SOFTWARE SELECTION默认的Minimal Install就好 INSTALLATION DE ...

  3. 快速切题 sgu135. Drawing Lines

    135. Drawing Lines time limit per test: 0.25 sec. memory limit per test: 4096 KB Little Johnny likes ...

  4. PostgresException: 42883: function ifnull(integer, integer) does not exist

    原因在于PostGresql并没有自带IFNULL函数,可以用COALESCE来替代IFNULL,且COALESCE功能更强大,可以输入更多参数,顺序判断并返回第一个非null值. 例如: SELEC ...

  5. Java——三大特性

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  6. 关于父类私有属性在子类构造函数中super调用的解释

    package test; public class Car { private int carMoney; //汽车租金 private String carName; //汽车名字 private ...

  7. memcache+php实现页面访问的加速

    一.什么是memcache memcache是目前主流的一个高性能的分布式内存对象缓存系统:它以key-value形式在内存中存储数据.由于数据缓存在内存中,所以相比操作DB而言,它不需要解析SQL. ...

  8. linux内存查看工具

    这里帮你总结了一下Linux下查看内存使用情况的多种方法~ 在做 Linux 系统优化的时候,物理内存是其中最重要的一方面.自然的,Linux 也提供了非常多的方法来监控宝贵的内存资源的使用情况.下面 ...

  9. navicat链接mysql 8 出现 2015 authentication plugin 'caching_sha2_password' 错误

    使用mysql自带的 MySQL 8.0 Command Line Client - Unicode 登录, 然后使用命令: alter user 'root'@'localhost' identif ...

  10. tf.cast()数据类型转换

    tf.cast()函数的作用是执行 tensorflow 中张量数据类型转换,比如读入的图片如果是int8类型的,一般在要在训练前把图像的数据格式转换为float32. cast定义: cast(x, ...