前一阵子在学习微信小程序开发,于是写一篇文章来记录一下~ (博客文章数喜加一

开发工具

值得一提的是微信专门为小程序和网页开发搞了一个IDE,名字毫无特色,就叫微信开发者工具,界面设计的倒还不算反人类,打开工具栏有一个叫调试(调戏)微信开发者工具的选项,才知道这个IDE差不多就是一个加了壳的网页,不过这样做确实方便调试

WMXL语法

虽然也算是HTML的变种,但是相对HTML修改了很多部分,比如HTML里的div相当于WXML里的view,img相当于image等等,另外大概超过一半的html元素在wxml里都被阉割,取而代之的是微信自己设计的开箱即用的组件,如scroll-view,swiper等,说实话,开发小程序的难度确实要比网页开发简单多了

MVVM框架

微信小程序的模式和目前的主流前端框架都使用了MVVM开发模式,由于之前也没有接触过这个领域,我去查了一下相关的资料。

MVVM是Model-View-ViewModel的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分开。

在WXML中,使用Mustache语法绑定动态数据,然后在page的js中注册相应的data,如此一来,只要在js中使用this.setData方法操作data的值,页面中绑定的数据就会动态刷新。另外,WXML也支持简单的双向数据绑定。

一开始使用这个模式来编程的时候确实不太习惯,不过后来适应了之后也觉得这种模式确实有优点。再到后来学习了Vue.js之后这种感觉更是明显。

页面的Js逻辑

小程序里的Page与安卓里的Activity一样有生命周期。在page加载时,会先调用Page.onLoad()方法作为入口,这一点类似于Activity.onCreate()方法。此外,小程序的生命生命周期中也有着onShow,onReady,onHide,onUnload等回调方法。

沉浸页面开发

我个人设计移动端页面的时候喜欢做全沉浸式界面,认为这样的界面简洁,优雅。下面是在为小程序做沉浸式界面时碰到的一些问题和解决方案。

沉浸式状态栏

由于我的页面是暗色的,首先要把状态栏调成亮色,然后把navigationBar调成自定义布局。
在单page目录下的json文件里添加:

1
2
3
4
{
"navigationStyle": "custom",
"navigationBarTextStyle": "white",
}

状态栏导航栏适配

因为把导航栏改成了自定义,所以我们就得为状态栏和导航栏做单独适配。

首先是获取状态栏的高度,然后再在根布局的上方留一个padding,微信为我们提供了获取状态栏高度的接口:

1
var statusHeight = wx.getSystemInfoSync().statusBarHeight

然后就是导航栏了,我们需要自己做一个顶端的导航栏,但是微信并没有提供导航栏高度相关的接口。为了实现效果,最终查到一种方法:

1
2
let menuBtn = wx.getMenuButtonBoundingClientRect()
var navHeight = (menuBtn.top - statusHeight) * 2 + menuBtn.height

微信小程序的页面右上方有一个小的菜单按钮,这里获取了按钮实例后,获取了它到屏幕顶端的距离和自身的高度,然后用距离减去状态栏高度再乘以2,最后加上自身的高度,得到的就是标题栏的高度。

实在是妙啊~

下拉刷新适配

由于自定义了顶栏,如果用原先Page上自带的onPullDownRefresh的话效果会十分丑陋,而且会把自定义的标题栏也拉下去。

通过查阅文档得知,scroll-view也有refresher,在WXML里对scroll-view做以下修改:

1
2
3
4
5
6
7
8
9
10
11
12
<scroll-view 
class="scroll-container"
scroll-y="true"
refresher-enabled="true"
refresher-default-style="white"
refresher-threshold="40"
refresher-triggered="{{refreshTriggered}}"
bindrefresherrefresh="refresh">

...

</scroll-view>

bindrefresherrefresh用来绑定刷新动作对应的方法,而refresher-triggered属性用来绑定当前刷新的状态,正在刷新则为true。

本来还可以自定义下拉刷新控件的样式,但由于默认效果已经足够,而自定义比较麻烦就放弃了这个想法。

底部导航栏

因为项目要求开发一个底部导航栏,而用微信提供的方法实现则与沉浸式界面十分的不搭,这里我有造了一波轮子,手动弄了一个导航栏。

底部导航栏的WXML:

1
2
3
4
5
6
7
8
<view class="nav-bar">
<view bindtap="switchTab" wx:key="index" wx:for="{{navbarItem}}" class="nav-bar-item-container" bindtap="switchTab{{item.index}}">
<view class="nav-bar-item">
<text class="material-icons" style="color:{{item.color}}">{{item.icon}}</text>
<text style="font-size: 12px;color:{{item.color}}">{{item.text}}</text>
</view>
</view>
</view>

WXSS里用的是flex弹性布局,因为代码比较多就不贴出来了,下面主要讲如何实现切换。

我们可以在布局里弄两个container,分别加上wx:if的判断,在js里加一个currentPage的data,导航栏绑定的tap事件是switchTab{{item.index}}然后定义不同的方法,如switchTab1,switchTab2等,来修改currentPage的值。下面是switchTab方法示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
switchTab1: function () {
var newNavBarItem = this.data.navbarItem
var _this = this
// 更改图标颜色
newNavBarItem[1].color = 'rgba(255,255,255,0.5)'
newNavBarItem[0].color = 'white'
// 加载页面切换的淡入动画
this.setData({
navbarItem: newNavBarItem,
animation2: 'fade-out',
animation1: 'fade-in'
})
// 动画加载完毕
setTimeout(function () {
_this.setData({
currentPage: 1
})
}, 200)
}

这样就优雅(个屁)的完成了导航栏的适配,甚至还加入了淡入的动画效果(这个上文没有提,改变class就行了)

后记

因为小程序开发的学习只是临时课程,这里我没有对小程序的API进行深层次的研究,所以个别做法可能会与正规的开发规范有一定出入,还请多多指教。