小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。
整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言
WXML
和WXSS
,以及基于JavaScript
的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。
框架的核心是一个响应的数据绑定系统,可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。
通过这个简单的例子来看:
Hello {{name}}!
// This is our App Service.
// This is our data.
var helloData = {
name: 'Weixin'
}
// Register a Page.
Page({
data: helloData,
changeName: function(e) {
// sent data change to view
this.setData({
name: 'MINA'
})
}
})
- 开发者通过框架将逻辑层数据中的 name 与视图层的 name 进行了绑定,所以在页面一打开的时候会显示 Hello Weixin!;
- 当点击按钮的时候,视图层会发送 changeName 的事件给逻辑层,逻辑层找到并执行对应的事件处理函数;
- 回调函数触发后,逻辑层执行 setData 的操作,将 data 中的 name 从 Weixin 变为 MINA,因为该数据和视图层已经绑定了,从而视图层会自动改变为 Hello MINA!。
框架 管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的生命周期。开发者需要做的只是将页面的数据、方法、生命周期函数注册到 框架 中,其他的一切复杂的操作都交由 框架 处理。
框架 提供了一套基础的组件,这些组件自带微信风格的样式以及特殊的逻辑,开发者可以通过组合基础组件,创建出强大的微信小程序 。
框架 提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。
框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。
将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层。
- WXML(WeiXin Markup language) 用于描述页面的结构。
- WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
- WXSS(WeiXin Style Sheet) 用于描述页面的样式。
- 组件(Component)是视图的基本组成单元。
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
要完整了解 WXML 语法,请参考 WXML 语法参考。
开发者通过框架将逻辑层数据中的 message 与视图层的 message 进行了绑定,所以在页面一打开的时候会显示 Hello MINA!
{{message}}
// page.js
Page({
data: {
message: 'Hello MINA!'
}
})
wx:for 遍历逻辑层array数据,界面将输出 1、2、3、4、5;
{{item}}
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5]
}
})
wx:if 条件判断,根据逻辑层数据判断视图层将输出哪些数据,该视图界面将显示 MINA ;
WEBVIEW
APP
MINA
// page.js
Page({
data: {
view: 'MINA'
}
})
FirstName: {{firstName}}, LastName: {{lastName}}
// page.js
Page({
data: {
staffA: {firstName: 'Hulk', lastName: 'Hu'},
staffB: {firstName: 'Shang', lastName: 'You'},
staffC: {firstName: 'Gideon', lastName: 'Nin'}
}
})
- 在wxml文件中使用template标签来引用"staffName"模板,并通过data属性传递员工的数据。这里使用了三个template标签,分别引用了staffA、staffB和staffC的数据。
- 在page.js文件中,通过Page函数定义了一个页面对象,并在data属性中定义了staffA、staffB和staffC的数据。每个员工对象包含了firstName和lastName属性,分别表示员工的名字和姓氏。
- 当小程序运行时,模板会根据传递的数据进行渲染,将员工的姓名显示在页面上。具体效果是,页面会显示三个员工的姓名:Hulk Hu、Shang You和Gideon Lin。
WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式,WXSS 用来决定 WXML 的组件应该怎么显示。
为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
与 CSS 相比,WXSS 扩展的特性有:
rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。
设备 | rpx换算px (屏幕宽度/750) | px换算rpx (750/屏幕宽度) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx |
建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束。
示例代码:
/** common.wxss **/
.small-p {
padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
padding:15px;
}
框架组件上支持使用 style、class 属性来控制组件的样式。
.
,样式类名之间用空格分隔。
目前支持的选择器有:
定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。、
WXS(WeiXin Script)是内联在 WXML 中的脚本段。通过 WXS 可以在模版中内联少量处理脚本,丰富模板的数据预处理能力。另外, WXS 还可以用来编写简单的 WXS 事件响应函数。
从语法上看, WXS 类似于有少量限制的 JavaScript 。要完整了解 WXS 语法,请参考WXS 语法参考。
对于小程序中的每个页面,都需要在页面对应的 js
文件中进行注册,指定页面的初始数据、生命周期回调、事件处理函数等。
详细的参数含义和使用请参考 Page 参考文档 。
使用 Page 构造器注册页面:简单的页面可以使用 Page()
进行构造。
代码示例:
//index.js
Page({
data: {
text: "This is page data."
},
onLoad: function(options) {
// 页面创建时执行
},
onShow: function() {
// 页面出现在前台时执行
},
onReady: function() {
// 页面首次渲染完毕时执行
},
onHide: function() {
// 页面从前台变为后台时执行
},
onUnload: function() {
// 页面销毁时执行
},
onPullDownRefresh: function() {
// 触发下拉刷新时执行
},
onReachBottom: function() {
// 页面触底时执行
},
onShareAppMessage: function () {
// 页面被用户分享时执行
},
onPageScroll: function() {
// 页面滚动时执行
},
onResize: function() {
// 页面尺寸变化时执行
},
onTabItemTap(item) {
// tab 点击时执行
console.log(item.index)
console.log(item.pagePath)
console.log(item.text)
},
// 事件响应函数
viewTap: function() {
this.setData({
text: 'Set some data for updating view.'
}, function() {
// this is setData callback
})
},
// 自由数据
customData: {
hi: 'MINA'
}
})
在小程序中所有页面的路由全部由框架进行管理。
框架以栈的形式维护了当前的所有页面。 当发生路由切换的时候,页面栈的表现如下:
路由方式 | 页面栈表现 |
---|---|
初始化 | 新页面入栈 |
打开新页面 | 新页面入栈 |
页面重定向 | 当前页面出栈,新页面入栈 |
页面返回 | 页面不断出栈,直到目标返回页 |
Tab 切换 | 页面全部出栈,只留下新的 Tab 页面 |
重加载 | 页面全部出栈,只留下新的页面 |
开发者可以使用 getCurrentPages()
函数获取当前页面栈。
对于路由的触发方式以及页面生命周期函数如下:
- 路由方式 触发时机 路由前页面 路由后页面
- 初始化 小程序打开的第一个页面 onLoad, onShow
- 打开新页面 调用 API wx.navigateTo
- 使用组件
onHide onLoad, onShow - 页面重定向 调用 API wx.redirectTo
- 使用组件
onUnload onLoad, onShow - 页面返回 调用 API wx.navigateBack
- 使用组件
- 用户按左上角返回按钮 onUnload onShow
- Tab 切换 调用 API wx.switchTab
- 使用组件
- 用户切换 Tab 各种情况请参考下表
- 重启动 调用 API wx.reLaunch
- 使用组件
onUnload onLoad, onShow
示例:
编写三个界面,并设置导航栏
{
"pages":[
"pages/index/index",
"pages/pageOne/pageOne",
"pages/pageTwo/pageTwo",
"pages/users/user",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "Weixin",
"navigationBarTextStyle":"black"
},
"tabBar": {
"list": [{
"pagePath": "pages/index/index",
"text": "首页"
}, {
"pagePath": "pages/pageOne/pageOne",
"text": "页面1"
}, {
"pagePath": "pages/pageTwo/pageTwo",
"text": "页面2"
}]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
编写两个按钮点击事件
页面1
编写事件跳转方法
// pages/pageOne/pageOne.js
Page({
/**
* 页面的初始数据
*/
data: {
},
//页面跳转
pageOneb: function(){
wx.switchTab({
url: '/pages/pageTwo/pageTwo',
})
},
userb: function(){
wx.navigateTo({
url: '/pages/users/user',
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
效果展示:
Tab 切换对应的生命周期(以 A、B 页面为 Tabbar 页面,C 是从 A 页面打开的页面,D 页面是从 C 页面打开的页面为例):
- onLoad --页面加载
- onReady --页面渲染
- onShow --页面显示
- onHide --页面隐藏
- onUnload --页面销毁
当前页面 路由后页面 触发的生命周期(按顺序)
A A Nothing happend
A B A.onHide(), B.onLoad(), B.onReady() ,B.onShow()
A B(再次打开) A.onHide(), B.onShow()
C A C.onUnload(), A.onShow()
C B C.onUnload(), B.onLoad(), B.onShow()
D B D.onUnload(), C.onUnload(), B.onLoad(), B.onShow()
D(从转发进入) A D.onUnload(), A.onLoad(), A.onShow()
D(从转发进入) B D.onUnload(), B.onLoad(), B.onShow()
总结
- 一级不会销毁
- 二级层级跳到层级低的会销毁
- 二级层级跳到高的只会隐藏
- 隔代中间所有页面会被销毁
注意事项
更多详情请参考管方文档:小程序框架