目录
1.框架简介
2.视图层 View
2.2 WXML
2.3 WXSS
2.4 JS
3.事件
4.逻辑层 APP service
4.1 生命周期
4.2 页面路由
4.3模块化
1.框架简介
小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。
整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)。小程序提供了自己的视图层描述语言
WXML
和WXSS
,以及基于JavaScript
的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,让开发者能够专注于数据与逻辑。响应的数据绑定
框架的核心是一个响应的数据绑定系统,可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。
通过这个简单的例子来看:
在开发者工具中预览效果
<!-- 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!
。页面管理
框架 管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的生命周期。开发者需要做的只是将页面的数据、方法、生命周期函数注册到 框架 中,其他的一切复杂的操作都交由 框架 处理。
基础组件
框架 提供了一套基础的组件,这些组件自带微信风格的样式以及特殊的逻辑,开发者可以通过组合基础组件,创建出强大的微信小程序 。
丰富的 API
框架 提供丰富的微信原生 API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。
参考文献:
微信开放文档微信开发者平台文档https://developers.weixin.qq.com/miniprogram/dev/reference/
2.视图层 View
2.1 WXML
WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。
要完整了解 WXML 语法,请参考WXML 语法参考。
用以下一些简单的例子来看看 WXML 具有什么能力:
数据绑定
<!--wxml-->
<view> {{message}} </view>
// page.js
Page({
data: {
message: 'Hello MINA!'
}
})
列表渲染
<!--wxml-->
<view wx:for="{{array}}"> {{item}} </view>
// page.js
Page({
data: {
array: [1, 2, 3, 4, 5]
}
})
条件渲染
<!--wxml-->
<view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view wx:elif="{{view == 'APP'}}"> APP </view>
<view wx:else="{{view == 'MINA'}}"> MINA </view>
// page.js
Page({
data: {
view: 'MINA'
}
})
模板
<!--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>
// page.js
Page({
data: {
staffA: {firstName: 'Hulk', lastName: 'Hu'},
staffB: {firstName: 'Shang', lastName: 'You'},
staffC: {firstName: 'Gideon', lastName: 'Lin'}
}
})
具体的能力以及使用方式在以下章节查看:
数据绑定、列表渲染、条件渲染、模板、引用
2.2 WXSS
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物理像素。
-
建议: 开发微信小程序时设计师可以用 iPhone6 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况。
样式导入
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束。
示例代码:
/** common.wxss **/
.small-p {
padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
padding:15px;
}
内联样式
框架组件上支持使用 style、class 属性来控制组件的样式。
style:静态的样式统一写到 class 中。style 接收动态的样式,在运行时会进行解析,请尽量避免将静态的样式写进 style 中,以免影响渲染速度。
<view style="color:{{color}};" />
class:用于指定样式规则,其属性值是样式规则中类选择器名(样式类名)的集合,样式类名不需要带上
.
,样式类名之间用空格分隔。<view class="normal_view" />
选择器
全局样式与局部样式
定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。
2.3 JS
/**
* 页面的初始数据
*/
data: {
name:"ruojuan",
array: [1, 2, 3, 4],
view: 'MINA',
staffA: {firstName: 'Hulk', lastName: '张建红'},
staffB: {firstName: 'Shang', lastName: 'ruojuan'},
staffC: {firstName: 'Gideon', lastName: 'mingjun'}
},
<!--pages/test/test.wxml-->
<!--<text>pages/test/test.wxml</text>-->
<!-- This is our View -->
<view> Hello {{name}}! </view>
<button bindtap="changeName"> Click me! </button>
<!-- <view wx:for="{{array}}"> wx:key="id" {{item}} </view> -->
<!--wxml-->
<view wx:for="{{array}}"> {{item}} </view>
<view wx:if="{{view == 'WEBVIEW'}}"> WEBVIEW </view>
<view wx:elif="{{view == 'APP'}}"> APP </view>
<view wx:else="{{view == 'MINA'}}"> MINA </view>
<!--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>
<!-- <template name="staffName">
<view>
FirstName: {{firstName1}}, LastName: {{lastName1}}
</view>
</template>
<template name="staffName">
<view>
FirstName: {{firstName2}}, LastName: {{lastName2}}
</view>
</template>
<template name="staffName">
<view>
FirstName: {{firstName3}}, LastName: {{lastName3}}
</view>
</template> -->
3.事件
参考文献:
事件 | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html
什么是事件
事件是视图层到逻辑层的通讯方式。
事件可以将用户的行为反馈到逻辑层进行处理。
事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
事件对象可以携带额外信息,如 id, dataset, touches。
事件的使用方式
-
在组件中绑定一个事件处理函数。
-
在相应的 Page 定义中写上相应的事件处理函数,参数是event。
如bindtap
,当用户点击该组件的时候会在该页面对应的 Page 中找到相应的事件处理函数。
tapName: function(event) {
console.log(event)
}
<view id="tapTest" data-hi="Weixin" data-meetingid="15672" bindtap="tapName"> Click me! </view>
4.逻辑层 APP service
小程序开发框架的逻辑层使用
JavaScript
引擎为小程序提供开发者JavaScript
代码的运行环境以及微信小程序的特有功能。逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。
开发者写的所有代码最终将会打包成一份
JavaScript
文件,并在小程序启动的时候运行,直到小程序销毁。这一行为类似 ServiceWorker,所以逻辑层也称之为 App Service。在
JavaScript
的基础上,我们增加了一些功能,以方便小程序的开发:
增加
App
和Page
方法,进行程序注册和页面注册。增加
getApp
和getCurrentPages
方法,分别用来获取App
实例和当前页面栈。提供丰富的 API,如微信用户数据,扫一扫,支付等微信特有能力。
提供模块化能力,每个页面有独立的作用域。
注意:小程序框架的逻辑层并非运行在浏览器中,因此
JavaScript
在 web 中一些能力都无法使用,如window
,document
等。
4.1 生命周期
参考文献:
生命周期 | 微信开放文档微信开发者平台文档https://developers.weixin.qq.com/miniprogram/dev/framework/app-service/page-life-cycle.html
案例:
创建一些文件:
可看见运行的生命周期:
跳转按钮
toC:function(event){
wx.navigateTo({
url: '/pages/r/r',
})
}
4.2 页面路由
在小程序中所有页面的路由全部由框架进行管理。
页面栈
框架以栈的形式维护了当前的所有页面。 当发生路由切换的时候,页面栈的表现如下:
开发者可以使用 getCurrentPages()
函数获取当前页面栈。
路由方式
对于路由的触发方式以及页面生命周期函数如下:
Tab 切换对应的生命周期(以 A、B 页面为 Tabbar 页面,C 是从 A 页面打开的页面,D 页面是从 C 页面打开的页面为例):
注意事项
navigateTo
,redirectTo
只能打开非 tabBar 页面。a--navigateTo--c, c-->redirectTo-->d
switchTab
只能打开 tabBar 页面。
reLaunch
可以打开任意页面。页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
调用页面路由带的参数可以在目标页面的
onLoad
中获取。
4.3模块化
模块化
可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块只有通过 module.exports 或者 exports
才能对外暴露接口。
注意:
-
exports
是 module.exports 的一个引用,因此在模块里边随意更改exports
的指向会造成未知的错误。所以更推荐开发者采用module.exports
来暴露模块接口,除非你已经清晰知道这两者的关系。 -
小程序目前不支持直接引入
node_modules
, 开发者需要使用到node_modules
时候建议拷贝出相关的代码到小程序的目录中,或者使用小程序支持的 npm 功能。
// common.js
function sayHello(name) {
console.log(`Hello ${name} !`)
}
function sayGoodbye(name) {
console.log(`Goodbye ${name} !`)
}module.exports.sayHello = sayHello
exports.sayGoodbye = sayGoodbye
在需要使用这些模块的文件中,使用 require
将公共代码引入;也可以使用import导入
var common = require('common.js')
Page({
helloMINA: function() {
common.sayHello('MINA')
},
goodbyeMINA: function() {
common.sayGoodbye('MINA')
}
})
文件作用域
在 JavaScript 文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。
通过全局函数 getApp
可以获取全局的应用实例,如果需要全局的数据可以在 App()
中设置,如:
// app.js App({ globalData: 1 }) // a.js // The localValue can only be used in file a.js. var localValue = 'a' // Get the app instance. var app = getApp() // Get the global data and change it. app.globalData++ // b.js // You can redefine localValue in file b.js, without interference with the localValue in a.js. var localValue = 'b' // If a.js it run before b.js, now the globalData shoule be 2. console.log(getApp().globalData)