一,框架
小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务
整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言
WXML
和WXSS
,以及基于JavaScript
的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑
1.1 响应的数据绑定
框架的核心是一个响应的数据绑定系统,可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新
通过这个简单的例子来看:
<!-- This is our View --> <view> Hello {{name}}! </view> <button bindtap="changeName"> Click me! </button> // 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
1.2 页面管理
框架 管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的生命周期。开发者需要做的只是将页面的数据、方法、生命周期函数注册到 框架 中,其他的一切复杂的操作都交由 框架 处理。
1.3 基础组件
框架 提供了一套基础的组件,这些组件自带微信风格的样式以及特殊的逻辑,开发者可以通过组合基础组件,创建出强大的微信小程序 。
1.4 丰富的 API
二、视图层 View
框架的视图层由 WXML 与 WXSS 编写,由组件来进行展示。
将逻辑层的数据反映成视图,同时将视图层的事件发送给逻辑层
WXML(WeiXin Markup language) 用于描述页面的结构。
WXS(WeiXin Script) 是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。
WXSS(WeiXin Style Sheet) 用于描述页面的样式
组件(Component)是视图的基本组成单元
2.1 WXML
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构
要完整了解 WXML 语法,请参考WXML 语法参考。
2.1.1 数据绑定
<!--wxml--> <view> {{message}} </view>
// page.js Page({ data: { message: 'Hello ZZ' } })
2.1.2 列表渲染
wx:for 遍历逻辑层array数据,界面将输出 1、2、3、4、5
<!--wxml--> <view wx:for="{{array}}"> {{item}} </view>
// page.js Page({ data: { array: [1, 2, 3, 4, 5] } })
2.1.3 条件渲染
wx:if 条件判断,根据逻辑层数据判断视图层将输出哪些数据,该视图界面将显示 MINA
<!--wxml--> <view wx:if="{{view == '1'}}"> WEBVIEW </view> <view wx:elif="{{view == '2'}}"> APP </view> <view wx:else="{{view == '3'}}"> MINA </view>
// page.js Page({ data: { view: 2 } })
2.1.4 模板
在wxml定义
<template name="staffName"> <view> FirstName: {{firstName}}, LastName: {{lastName}} </view> </template> <template is="staffName" data="{{...staffA}}"></template> <template is="staffName" data="{{...staffB}}"></template> <template is="staffName" data="{{...staffC}}"></template>
js中定义:
// page.js Page({ data: { staffA: { firstName: 'Hulk', lastName: 'Hu' }, staffB: { firstName: 'Shang', lastName: 'You' }, staffC: { firstName: 'Gideon', lastName: 'Lin' } } })
在wxml文件中使用template标签来引用"staffName"模板,并通过data属性传递员工的数据。这里使用了三个template标签,分别引用了staffA、staffB和staffC的数据
在page.js文件中,通过Page函数定义了一个页面对象,并在data属性中定义了staffA、staffB和staffC的数据。每个员工对象包含了firstName和lastName属性,分别表示员工的名字和姓氏。
当小程序运行时,模板会根据传递的数据进行渲染,将员工的姓名显示在页面上。具体效果是,页面会显示三个员工的姓名:Hulk Hu、Shang You和Gideon Lin
2.2 WXSS
WXSS (WeiXin Style Sheets)是一套样式语言,用于描述 WXML 的组件样式。
WXSS 用来决定 WXML 的组件应该怎么显示
为了适应广大的前端开发者,WXSS 具有 CSS 大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
与 CSS 相比,WXSS 扩展的特性有:
- 尺寸单位
- 样式导入
2.2.1 尺寸单位
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 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况
事件!!!
- 事件是视图层到逻辑层的通讯方式。
- 事件可以将用户的行为反馈到逻辑层进行处理。
- 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
- 事件对象可以携带额外信息,如 id, dataset, touches
实例:
wxml定义:
<view id="tapTest" data-hi="Weixin" data-meettingSteate="6" bindtap="tapName"> Click me! </view>
page.js定义
tapName: function (event) { console.log(event) console.log(event.target.dataset) },
效果:
2.2.2 样式导入
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束
示例代码:
/** common.wxss **/ .small-p { padding:5px; }
/** app.wxss **/ @import "common.wxss"; .middle-p { padding:15px; }
2.2.3 内联样式
框架组件上支持使用 style、class 属性来控制组件的样式。
- style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度
<view style="color:{{color}};" />
- class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上
.
,样式类名之间用空格分隔
<view class="normal_view" />
2.2.3 选择器
目前支持的选择器有:
选择器 | 样例 | 样例描述 |
.class | .intro |
选择所有拥有 class="intro" 的组件 |
#id | #firstname |
选择拥有 id="firstname" 的组件 |
element | view |
选择所有 view 组件 |
element, element | view, checkbox |
选择所有文档的 view 组件和所有的 checkbox 组件 |
::after | view::after |
在 view 组件后边插入内容 |
::before | view::before |
在 view 组件前边插入内容 |
2.2.4 全局样式与局部样式
定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器
2.3 WXS
WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML
,可以构建出页面的结构
示例
- 新建一个wxs文件
var toDecimal2 = function (x) { var f = parseFloat(x); if (isNaN(f)) { return '0.00' } var f = Math.round(x * 100) / 100; var s = f.toString(); var rs = s.indexOf('.'); if (rs < 0) { rs = s.length; s += '.'; } while (s.length <= rs + 2) { s += '0'; } return s; } //module.exports = toDecimal2 module.exports = { toDecimal2:toDecimal2 }
- 在wxml中使用
<!--pages/c/c.wxml--> <wxs src="../../wxs/PageUtils.wxs" module="PageUtils"></wxs> <wxs module="m1"> var msg = "hello world"; module.exports.message = msg; </wxs> <view> <text>pages/c/c.wxml,</text> <text>{{m1.message}}</text> <view> <text>{{PageUtils.toDecimal2(123.453)}}</text> </view> <view> <button type="primary" bindtap="jump">跳转到D页面</button> </view> </view>
注意事项
- WXS 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。
- WXS 与 JavaScript 是不同的语言,有自己的语法,并不和 JavaScript 一致。
- WXS 的运行环境和其他 JavaScript 代码是隔离的,WXS 中不能调用其他 JavaScript 文件中定义的函数,也不能调用小程序提供的API。
- WXS 函数不能作为组件的事件回调。
- 由于运行环境的差异,在 iOS 设备上小程序内的 WXS 会比 JavaScript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异。
以下是一些使用 WXS 的简单示例,要完整了解 WXS 语法,请参考WXS 语法参考
页面渲染
<!--wxml--> <wxs module="m1"> var msg = "hello world"; module.exports.message = msg; </wxs> <view> {{m1.message}} </view>
页面输出:
hello world
数据处理
// page.js Page({ data: { array: [1, 2, 3, 4, 5, 1, 2, 3, 4] } }) <!--wxml--> <!-- 下面的 getMax 函数,接受一个数组,且返回数组中最大的元素的值 --> <wxs module="m1"> var getMax = function(array) { var max = undefined; for (var i = 0; i < array.length; ++i) { max = max === undefined ? array[i] : (max >= array[i] ? max : array[i]); } return max; } module.exports.getMax = getMax; </wxs> <!-- 调用 wxs 里面的 getMax 函数,参数为 page.js 里面的 array --> <view> {{m1.getMax(array)}} </view>
页面输出:
5
三、小程序生命周期
小程序开发框架的逻辑层使用 JavaScript 引擎为小程序提供开发 JavaScript 代码的运行环境以及微信小程序的特有功能
逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
开发者写的所有代码最终将会打包成一份 JavaScript 文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。
在 JavaScript 的基础上,我们增加了一些功能,以方便小程序的开发:
- pp 和 Page 方法,进行程序注册和页面注册。
- 增加 getApp 和 getCurrentPages 方法,分别用来获取 App 实例和当前页面栈。
- 提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
- 提供模块化能力,每个页面有独立的作用域。
注意:小程序框架的逻辑层并非运行在浏览器中,因此 JavaScript 在 web 中一些能力都无法使用,如 window,document 等增加 A
准备
首先准备四个页面分别是a\b\c\d,其中a和b是一级菜单,c和d是二级菜单,并在这些页面中添加按钮设置相对应的点击事件遵循navigateTo
, redirectTo
只能打开非 tabBar 页面和switchTab
只能打开 tabBar 页面的原则
部分代码展示
app.json:
{ "pages":[ "pages/index/index", "pages/a/a", "pages/b/b", "pages/c/c", "pages/d/d", "pages/logs/logs" ], "window":{ "backgroundTextStyle":"light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "Weixin", "navigationBarTextStyle":"black" }, "tabBar": { "list": [{ "pagePath": "pages/index/index", "text": "首页" }, { "pagePath": "pages/a/a", "text": "A页面" },{ "pagePath": "pages/b/b", "text": "B页面" }] }, "style": "v2", "sitemapLocation": "sitemap.json" }
a.wxml:
<!--pages/a/a.wxml--> <text>pages/a/a.wxml</text> // a.wxml <text>我是一级菜单A页面</text> <button bindtap="a2b">A页面跳转B页面</button> <button bindtap="a2c">A页面跳转C页面</button> <button bindtap="a2d">A页面跳转d页面</button>
a.js:
a2b:function(){ wx.switchTab({ url: '/pages/b/b', }) }, a2c:function(){ wx.navigateTo({ url: '/pages/c/c', }) }, a2d:function(){ wx.navigateTo({ url: '/pages/d/d', }) },
其他跳转根据自己需求定义即可!
总结
一级不会销毁
二级层级深跳到层级低的会销毁二级层级低跳到高的只会隐藏隔代中间所有页面会被销毁