微信小程序开发零基础入门
上QQ阅读APP看书,第一时间看更新

3.1 逻辑层

小程序开发框架的逻辑层又称为App Service,是由JavaScript编写和实现的。开发者写的所有代码最后将被打包成一份JavaScript,并在小程序启动的时候运行,直到小程序被销毁。

逻辑层的主要作用是处理数据后发送给视图层渲染以及接收视图层的事件反馈。

为了更方便地进行项目开发,小程序在JavaScript的基础上进行了一些优化,例如:

(1)新增App()和Page()方法,分别用于整个应用程序和单独页面的注册。

(2)新增getApp()和getCurrentPages()方法,分别用于获取整个应用实例和当前页面实例。

(3)提供丰富的微信原生API,例如可以方便地获取微信用户信息、本地存储、扫一扫、微信支付、微信运动等特殊功能。

(4)每个页面具有独立的作用域,并提供模块化功能。

需要注意的是,由于框架不在浏览器中运行,所以JavaScript与浏览器相关的一些功能无法使用,例如document、window等。

3.1.1 注册程序

1 App()方法

小程序通过使用App(OBJECT)方法进行应用注册,用其指定小程序的生命周期函数。

OBJECT参数如表3-1所示。

表3-1 App()方法的OBJECT参数

注意:App()方法只能写在小程序根目录下的app.js文件中,并且只能注册1个。

用户可以使用微信web开发者工具在空白app.js文件中直接输入关键词app,此时会自动出现提示列表,如图3-1所示。

图3-1 app.js的代码提示列表

默认选择提示列表中的第一项,直接按回车键就可以自动生成带有生命周期全套函数的代码结构,如图3-2所示。

图3-2 app.js自动生成App()代码

事实上,App()中的这些函数均为可选函数,开发者可以根据实际需要删除其中的部分函数,或保留这些函数但空着不填充内容。

第12、19行注释语句均提到了小程序后台和前台的概念,具体说明如下。

• 小程序后台:指的是小程序没有在手机当前画面显示,但是并没有被销毁。当用户单击左上角的按钮关闭小程序或者按设备的Home键离开微信时会进入后台运行状态。

• 小程序前台:指的是小程序在手机当前画面被使用。当用户再次打开处于后台运行状态的小程序时会重新进入前台运行状态。

注意:只有当小程序进入后台一定时间或者系统资源占用过高时才会被真正地销毁。

由图3-2中的代码可见,onLaunch()、onShow()和onError()方法在触发时均会返回参数,用户可以利用这些参数进行状态的判断与处理。其中,onLaunch()与onShow()方法返回的参数名称完全相同,具体如表3-2所示。

表3-2 onLaunch()和onShow()方法返回的参数

支持返回referrerInfo.appId的场景值如表3-3所示。

表3-3 支持返回referrerInfo.appId的场景值

说明:关于场景值的更多介绍,见附录。

除了函数外,App()也支持添加自定义的全局变量,示例代码如下:

这里,全局变量的名称、取值和数量都可以由开发者自定义。

2 onPageNotFound()方法

当需要打开的页面不存在时,微信客户端会有一个原生模板页面提示。如果开发者不希望跳转到此页面,想自行处理,则需用到onPageNotFound()方法。

该方法从基础库1.9.90开始支持,低版本需要做兼容处理。当要打开的页面并不存在时,会回调这个方法并带有3个参数,具体参数内容如表3-4所示。

表3-4 onPageNotFound()方法的参数

onPageNotFound()方法的示例代码如下:

上述代码可以用指定的页面代替原生模板页面。需要注意的是,如果onPageNotFound()回调中又重定向到另一个不存在的页面,将重定向到微信自带的原生模板页面提示页面不存在,并且不再触发onPageNotFound()监听。

3 getApp()方法

在小程序的其他JS文件中均可以使用全局的getApp()方法获取小程序实例。

例如,test.js,示例代码如下:

1. var app=getApp()
2. console.log(app.globalData.userInf)

此时,就可以在test.js页面获得app.js中保存的公共数据,并在console控制台打印输出。

需要注意的是,用户不可以在app.js的App()函数内部调用getApp()方法,可以直接使用关键字this代替。例如:

上述代码就在onLoad()方法中直接使用了this关键字获得全局变量。

3.1.2 注册页面

小程序在每个页面JS文件中通过使用Page(OBJECT)方法进行页面注册,该方法可以用于指定小程序页面的生命周期函数。Page()方法的OBJECT参数如表3-5所示。

表3-5 Page()方法的OBJECT参数

注意:Page()方法只能写在小程序每个页面对应的JS文件中,并且每个页面只能注册1个。

在微信web开发者工具中新建页面时会自动生成页面JS文件的Page()方法。这里以test页面为例,创建完成后test.js的代码如下:

与App()方法的函数情况类似,开发者同样可以根据实际情况删除Page()中不需要的函数,或者保留该函数内部为空白。

除了函数外,Page()同样也支持添加自定义的页面变量,示例代码如下:

这里,变量的名称、取值和数量也都可以由开发者自定义。

1 初始数据

在Page()方法中默认生成的第一项就是data属性,该属性是页面第一次渲染使用的初始数据。当页面加载时,data将会以JSON字符串的形式由逻辑层传至渲染层,因此data中的数据必须是可以转成JSON的类型,例如字符串、数字、布尔值、对象、数组。渲染层可以通过WXML对数据进行绑定。

例如在data中放置两个自定义数据,页面JS文件的示例代码如下:

对应WXML的示例代码如下:

<view>{{msg01}} {{msg02}}</view>

此时{{msg01}}和{{msg02}}不会显示字面内容,而是会查找data中的初始数据,然后显示出“Hello 2018”字样。

2 生命周期回调函数

Page()函数中默认生成的onLoad()、onShow()、onReady()、onHide()以及onUnload()均属于页面的生命周期回调函数,具体说明如下。

• onLoad():格式为onLoad(Object query),只在页面加载时触发一次,可以在onLoad()的参数中获取打开当前页面路径附带的参数。

• onShow():当页面显示或从小程序后台切入前台时触发。

• onReady():当页面初次渲染完成时触发。注意,一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互。

• onHide():当页面隐藏/切入后台时触发。例如navigateTo或底部tab切换到其他页面,小程序切入后台等。

• onUnload():当页面卸载时触发。例如redirectTo或navigateBack到其他页面时。

3 页面事件处理函数

Page()方法中默认生成的onPullDownRefresh()、onReachBottom()、onShareAppMessage()以及未自动生成的onPageScroll()、onTabItemTap()均属于页面事件处理函数,具体说明如下。

• onPullDownRefresh():监听用户下拉刷新事件,需要在app.json的window选项中或页面配置中开启enablePullDownRefresh。

• onReachBottom():监听用户上拉触底事件,可以在app.json的window选项中或页面配置中设置触发距离onReachBottomDistance。在触发距离内滑动期间,本事件只会被触发一次。

• onPageScroll(OBJECT):监听用户滑动页面事件。其参数OBJECT具有唯一属性scrollTop,该属性为Number类型,表示页面在垂直方向已滚动的距离(单位为px)。

• onShareAppMessage(OBJECT):监听用户单击页面内“转发”按钮(<button>按钮组件,其属性值open-type="share")或右上角菜单“转发”按钮的行为,并且自定义转发内容。其OBJECT参数如表3-6所示。

表3-6 onShareAppMessage()方法的OBJECT参数

此事件需要返回一个Object对象,用于自定义转发内容,返回内容如表3-7所示。

表3-7 onShareAppMessage()方法的返回的Object对象

onShareAppMessage(OBJECT)方法的示例代码如下:

说明:第8行引号中的/page/user是自定义页面地址,id=123是自定义参数内容。

• onTabItemTap(OBJECT):单击tab时触发,从基础库1.9.0开始支持,低版本需做兼容处理。其OBJECT参数如表3-8所示。

表3-8 onTabItemTap()方法的OBJECT参数

onTabItemTap(OBJECT)方法的示例代码如下:

4 组件事件处理函数

Page()方法中还可以定义组件事件处理函数,在WXML页面的组件上添加事件绑定,当事件被触发时就会主动执行Page()中对应的事件处理函数。

例如tap就是单击事件,可以使用bindtap属性在组件上进行绑定。这里以<button>按钮组件为例,为其绑定单击事件的WXML相关代码如下:

<button bindtap="btnTap">单击此处</button>

在JS的Page()方法中相关代码如下:

除了bindtap可以绑定单击事件外,还有很多事件,详见3.2.1节“WXML”。

5 route

在Page()方法中可以使用this.route查看当前页面的路径地址。例如:

6 setData()

在Page()方法中,setData()可以用来同步更新data属性中的数据值,也能异步更新相关数据到WXML页面上。其参数说明如表3-9所示。

表3-9 setData()参数

例如在Page()的data中定义初始数据,JS文件代码如下:

此时WXML页面的{{today}}初始值为2018-01-01。

为组件追加自定义单击事件changeData,WXML页面代码如下:

<view bindtap="changeData">{{today}} </view>

在Page()中追加自定义函数changeData()的具体内容,JS文件代码如下:

如果用户触发了该组件的单击事件,WXML中的{{today}}值将立刻更新成2018-09-09。

setData()方法在使用时不是必须事先在Page()方法的data中定义初始值,可以在data数据空白的情况下直接用该方法设置一些新定义的变量。

如果想读取data中的数值,可以使用this.data的形式。例如,上述代码如果只是想获得当前today值,可以用this.data.today表示。

7 生命周期

小程序应用与页面有各自的生命周期函数,它们在使用过程中也会互相影响。

小程序应用生命周期如图3-3所示。

图3-3 小程序应用生命周期

小程序在被打开时会首先触发onLaunch()进行程序启动,完成后调用onShow()准备展示页面,如果被切换进入后台会调用onHide(),直到下次程序在销毁前重新被唤起会再次调用onShow()。

小程序页面生命周期如图3-4所示。

图3-4 小程序页面生命周期

在小程序应用生命周期调用完onShow()以后就准备触发小程序页面生命周期了。页面初次打开会依次触发onLoad()、onShow()、onReady()这3个函数。同样,如果被切换到后台,会调用页面onHide(),从后台被唤醒会调用页面onShow()。直到页面关闭会调用onUnload(),下次打开还会依次触发onLoad()、onShow()、onReady()这3个函数。

需要注意的是,tab页面的互相切换以及在当前页面上打开一个新页面都不算页面关闭,只是起到了隐藏的作用。这几种情况只会触发onHide(),回到此页面只触发onShow(),具体情况见3.1.3节“页面路由”。

3.1.3 页面路由

1 页面栈

在小程序中页面之间的切换路由均由框架统一进行管理,框架以栈的形式维护了当前的所有页面。当发生路由切换的时候,页面栈的表现如表3-10所示。

表3-10 路由方式与页面栈的表现

2 获取页面栈

小程序使用getCurrentPages()方法获取当前页面栈的实例,实例将以数组形式按栈的顺序给出。其中,第一个元素为首页,最后一个元素为当前页面。

3 路由方式

路由方式及页面生命周期函数如表3-11所示。

表3-11 路由方式与页面生命周期函数

<navigator>的用法见第4章“小程序组件”,API的用法见第11章“界面API”。

由于tab页面的切换情况比较复杂,这里用A、B、C、D几个页面举例说明。假设其中A、B为tabBar页面,C是从A打开的页面,D是从C打开的页面,tab切换对应的生命周期如表3-12所示。

表3-12 tab切换对应的生命周期函数

3.1.4 模块化

1 文件的作用域

在小程序的任意JS文件中声明的变量和函数只在该文件中有效,不同的JS文件中可以声明相同名字的变量和函数,不会互相影响。

如果需要跨页面进行数据共享,可以在app.js中定义全局变量,然后在其他JS文件中使用getApp()获取和更新。例如在app.js中设置全局变量msg,代码如下:

假设在test.js文件中希望修改全局变量msg的值,代码如下:

此时在任意其他JS文件中再读取msg的值都会是更新后的内容。

2 模块的调用

小程序支持将一些公共JavaScript代码放在一个单独的JS文件中,作为一个公共模块,可以被其他JS文件调用。注意,模块只能通过module.exports或者exports对外提供接口。

例如在根目录下新建utils文件夹并创建公共JS文件common.js,代码如下:

上述代码创建了两个自定义函数,即sayHello()和sayGoodbye(),且都带有参数name。需要注意的是,exports是module.exports的一个引用,因此在模块中随意更改exports的指向会造成未知错误。

在页面JS中使用require引用common.js文件,此时可以调用其中的函数,代码如下:

3.1.5 API

小程序开发框架提供丰富的微信原生API接口,可以方便地调用微信提供的功能,例如获取用户信息、本地存储、地理定位等。常用的API如下。

• 网络:实现小程序与服务器端的网络交互。

• 媒体:实现图片、录音、音/视频和相机管理。

• 文件:实现临时文件和本地文件的管理。

• 数据:实现小程序本地数据的缓存。

• 位置:使用小程序获取地理位置和控制地图组件。

• 设备:获得手机内存、网络、传感器、扫码、剪贴板、振动等功能。

• 界面:实现交互反馈、导航条设置、页面导航、动画、绘图等功能。

这些API及其相关标签会在后续章节陆续介绍。