小程序 逻辑层 概述:
小程序开发框架的逻辑层使用 JavaScript
引擎为小程序提供开发者 JavaScript
代码的运行环境以及微信小程序的特有功能。
逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
开发者写的所有代码最终将会打包成一份 JavaScript
文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。
在 JavaScript
的基础上,我们增加了一些功能,以方便小程序的开发:
- 增加
App
和Page
方法,进行程序注册和页面注册。 - 增加
getApp
和getCurrentPages
方法,分别用来获取App
实例和当前页面栈。 - 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
- 提供模块化能力,每个页面有独立的作用域。
注意:小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript
在 web 中一些能力都无法使用,如 window
,document
等。
app.js 中 APP方法:
每个小程序都需要在 app.js
中调用 App
方法注册小程序实例,绑定生命周期回调函数、错误监听和页面不存在监听函数等。
下面我们看 App() 里所绑定的 生命周期 方法,
1,onLaunch(options):
调用时机:小程序被加载完毕的时候调用。这个方法一般用来做一些初始化的事情。比如获取用户信息、获取历史缓存信息、获取小程序打开来源等。
参数:
| 参数 | 类型 | 说明 |
| path | String | 打开小程序的路径 |
| query | Object | 打开小程序的query |
| scene | Number | 打开小程序的场景值 |
| shareTicket | String | shareTicket,详见 获取更多转发信息 |
| referrerInfo | Object | 当场景为由从另一个小程序或公众号或App打开时,返回此字段 |
| referrerInfo.appId | String | 来源小程序或公众号或App的 appId,详见下方说明 |
| referrerInfo.extraData | Object | 来源小程序传过来的数据,scene=1037或1038时支持 |
这就是onLauch() 当小程序 被加载完毕之后,就会执行它,
2,onShow(options):
调用时机:小程序启动,或从后台进入前台显示时调用。
如果想要在小程序每次进入到前台的时候都执行一些事情,那么可以把代码放在这个里面。比如一些实时动态更改的数据,用户每次进来都要从服务器更新,那么我们就可以在这个里面做。
参数:同onLaunch 。
onShow 和 onLaunch 的区别:
onShow可能被调用多次, onLauch 调用一次,
3, onHide():
调用时机:小程序被切换到后台(包括微信自身被切换到后台或者小程序暂时被切换到后台时)。可以在这个方法中做一些数据的保存。
参数:无。
4, onError(String error):
调用时机:小程序发生脚本错误,或者 api 调用失败时触发。
在小程序发生错误的时候,会把错误信息发送到这个函数中,所以可以在这个函数中做一些错误收集。
参数:error。
getApp() 函数:
获取当前的app
对象。一般在其他的page
页面中调用。有以下两个注意点:
- 不要在定义于 App() 内的函数中调用 getApp() ,使用 this 就可以拿到 app 实例。
- 通过 getApp() 获取实例之后,不要私自调用生命周期函数。
具体页面.js 中的Page方法 :
Page(Object)
函数用来注册一个页面。接受一个 Object 类型参数,其指定页面的初始数据、生命周期回调、事件处理函数 等。
数据渲染:
在 模板中需要使用 的数据,需要放在 Page 中的对象的
的data
属性中,
如果以后想要修改data
中的值,应该使用setData
方法。setData
函数用于将数据从逻辑层发送到视图层(异步),同时改变对应的 this.data 的值(同步)。
注意事项:
- 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
- 放到
data
中的值,只能使用可以JSON
序列化的:字符串,数字,布尔值,对象,数组。否则将不会渲染(例如函数不可以被序列化)。 - 其中
key
可以以数据路径的形式给出,支持改变数组中的某一项或对象的某个属性,如array[2].message
,a.b.c.d
,并且不需要在this.data
中预先定义。
有关于上面的第3条:
修改后的效果:
可以 直接这样修改, 比较方便!!! 但是对于比较复杂的数据修改还是要 采用 先将 data 取出来 ,然后再修改,
补充:
上面的代码实现的是 每次点击都将 获取全局 globalData中的数字,然后使用,最后加1并写入 全局data 中!
Page() 方法中 的生命周期函数 :
它们的调用顺序:
onLoad ,onShow , onReady
如果切入后台,就会调用 onHide
如果切入前台,就又会调用onShow
onLoad(Object query):
它类似于 App () 方法 中的 onLaunch() 方法,
页面加载时触发。一个页面只会调用一次,可以在 onLoad的参数中获取打开当前页面路径中的参数。一般建议在这个函数中做一些页面的数据初始化工作。
onShow():
页面显示/切入前台时触发。比如新推入了一个新的页面,那么原来的页面就处于后台,这时候如果把新页面又移除掉,那么下面的页面就会调用onShow方法。
onReady():
页面初次渲染完成时触发。一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交互了。
对界面内容进行设置的 API 如wx.setNavigationBarTitleText
,比较合适在这个里面执行。
onHide()
页面隐藏/切入后台时触发。如navigateTo
或底部tab
切换到其他页面,小程序切入后台等。
onUnload()
页面卸载时触发。
如redirectTo
或navigateBack
到其他页面时。
一开始跳转到一个页面,然后从该页面返回后 ,就会卸载该页面
页面路由:
在小程序中所有页面的路由全部由框架进行管理。
框架以栈的形式维护了当前的所有页面。
当发生路由切换的时候,页面栈的表现如下:
路由方式 | 页面栈表现 |
---|---|
初始化 | 新页面入栈 |
打开新页面 | 新页面入栈 |
页面重定向 | 当前页面出栈,新页面入栈 |
页面返回 | 页面不断出栈,直到目标返回页 |
Tab 切换 | 页面全部出栈,只留下新的 Tab 页面 |
重加载 | 页面全部出栈,只留下新的页面 |
开发者可以使用 getCurrentPages()
函数获取当前页面栈 数组 。
getCurrentPages 的使用:
我们在跳转 过去的页面的js中 打印 pageStack:
getCurrentPages 的实际 使用:
主要思路就是通过 getCurrentPages() 获取到page 对象,然后就可以获取它里面的 data 数据,并可以将操作后的数据 setData() 回去,
发布微博案例:
代码:
1 <view wx:for="{{contents}}">{{item}}</view> 2 3 <button bindtap="onClickEvt">去发微博</button>
1 /* pages/weibo_list/weibo_list.wxss */ 2 view{ 3 height: 80rpx; 4 line-height: 80rpx; 5 border-bottom: 1px solid #f00; 6 7 8 } 9 10 button{ 11 margin-top: 50rpx; 12 13 }
1 // pages/weibo_list/weibo_list.js 2 Page({ 3 4 /** 5 * 页面的初始数据 6 */ 7 data: { 8 contents:["Talk is cheap,show me code","To be or not to be is a question"] 9 }, 10 11 /** 12 * 生命周期函数--监听页面加载 13 */ 14 onLoad: function (options) { 15 16 }, 17 onClickEvt:function(){ 18 wx.navigateTo({ 19 url: '/pages/fabu/fabu', 20 }) 21 22 } 23 })
1 <!--pages/fabu/fabu.wxml--> 2 <view> 3 <form bindsubmit="onSubmitEvt"> 4 <textarea name="content" placeholder="请在此处输入你要发布的内容"></textarea> 5 <button form-type="submit">提交</button> 6 </form> 7 </view>
1 // pages/fabu/fabu.js 2 Page({ 3 4 /** 5 * 页面的初始数据 6 */ 7 data: { 8 }, 9 10 /** 11 * 生命周期函数--监听页面加载 12 */ 13 onLoad: function (options) { 14 15 }, 16 onSubmitEvt:function(evt){ 17 var content = evt.detail.value.content; 18 // 然后将 content 设置到上个页面中去, 19 20 var page_stacks = getCurrentPages(); 21 var pre_idx = page_stacks.length - 2; 22 23 // 获取到 上个page 24 var page = page_stacks[pre_idx]; 25 var contents = page.data.contents; 26 contents.push(content); 27 page.setData({contents:contents}); 28 29 wx.navigateBack({ }); 30 31 } 32 33 34 35 36 })
form 表单提交:
这里有关的 form 表单的提交:
都要有, 这样,当点击 提交的时候,数据才会以key-value 的形式保存起来, key的名字是 name 的值!!!