小程序学习笔记之代码构成与框架结构

导言

小程序的项目代码文件大致分为JSON配置文件、WXML模板文件、WXSS样式文件、JS脚本逻辑文件。
小程序的框架MINA的核心是一个响应的数据绑定系统,也体现了MVVM的开发模式。小程序并不是“正宗”的MVVM,它是单向绑定的。

代码构成

项目目录

官方提供的quickstart例子的项目目录如下
wx_quickstart
├── app.js
├── app.json
├── app.wxss
├── pages
│ ├── index
│ │ ├── index.js
│ │ ├── index.wxml
│ │ └── index.wxss
│ └── logs
│ ├── logs.js
│ ├── logs.json
│ ├── logs.wxml
│ └── logs.wxss
├── project.config.json
└── utils
└── util.js
可以看到,文件大致分为这4种

  1. .json 后缀的 JSON 配置文件
  2. .wxml 后缀的 WXML 模板文件
  3. .wxss 后缀的 WXSS 样式文件
  4. .js 后缀的 JS 脚本逻辑文件

app.json

以下是一个包含了所有配置选项的app.json。
配置了页面文件的路径、窗口表现、设置网络超时时间、设置多tab等。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
"pages": [
"pages/index/index",
"pages/logs/index"
],
"window": {
"navigationBarTitleText": "Demo"
},
"tabBar": {
"list": [{
"pagePath": "pages/index/index",
"text": "首页"
}, {
"pagePath": "pages/logs/logs",
"text": "日志"
}]
},
"networkTimeout": {
"request": 10000,
"downloadFile": 10000
},
"debug": true
}

wxml

wxml (WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。它的作用和html一样,都是负责页面的结构。
基础组件包括:视图容器、基础内容、表单组件、导航、媒体组件、地图、画布、开放能力等。详细可以看官方文档的组件介绍。
wxml的能力主要有以下几点:

  1. 数据绑定
    使用 Mustache 语法(双大括号)将变量包起来,可以在双大括号内进行简单的运算,如三元运算等
  2. 列表渲染
    在组件上使用wx:for控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。
  3. 条件渲染
    在框架中,使用wx:if来判断是否需要渲染该代码块
  4. 模板
    wxml提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。
  5. 事件
    wxml的冒泡事件有:touchstarttaplongpresstransitionendtouchforcechange等,触摸类事件支持捕获阶段。
    可以在组件中绑定一个事件处理函数,事件绑定的写法以 key、value 的形式。key是bind则是普通的事件绑定,如bindtapbind:tapcatch事件绑定可以阻止冒泡事件向上冒泡;capture-bind在捕获阶段监听事件;capture-catch则中断捕获阶段和取消冒泡阶段。

wxss

wxss (WeiXin Style Sheets)是一套样式语言,用于描述WXML的组件样式。它的作用和css一样,都是负责页面的样式。
css相比,wxss的特性有

  1. 尺寸单位
    rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx (iphone6) 。即,以750rpx为基准,对于不同大小的屏幕放大或缩小。因此,设计师可以用 iPhone6 作为视觉稿的标准。
    rpx

  2. 样式导入
    使用@import语句可以导入外联样式表。

  3. 选择器
    比起css,只支持部分选择器,包括.class#idelementelement, element::after::before
  4. 全局样式与局部样式
    定义在 app.wxss 中的样式为全局样式,作用于每一个页面。在 page 的 wxss 文件中定义的样式为局部样式,只作用在对应的页面,并会覆盖 app.wxss 中相同的选择器。
  5. 本地资源无法通过 css 获取
    因此,在设置background-image属性时,可以使用网络图片,或者 base64,或者使用标签代替;在设置@font-facesrc属性时,需要把字体文件转换成base64,可以到https://transfonter.org/转换。

js

需要注意的一点是:小程序的js运行环境是JsCore,不是浏览器,不能使用window与document对象。
zepto/jquery会使用到window对象和document对象,所以也无法使用。

JsCore(JavaScriptCore)
对JS进行解析和提供执行环境。iOS7后苹果推出,极大地方便了我们对js的操作。我们可以脱离webview直接运行我们的js。JSCore 只是实现了标准 JavaScript 语言,所以也自然就没有浏览器对象(BOM)等。微信小程序框架的native端与js端通过JsCore来相互通信。

框架结构

MINA

小程序的框架MINA的核心是一个响应的数据绑定系统,也体现了MVVM的开发模式(例如 React, Vue)的思想。
下面就是MVVM的框架结构
mvvm

  • View:视图
  • ViewModel:与视图数据绑定;获取Model的变更,在必要时更新View
  • Model:数据(与后端的沟通、AJAX请求以及对数据的处理)

小程序的框架结构如下:
structure
渲染的过程是这样的:

  1. 提供了JavsScript运行环境(JsCore),由JavaScript编写的业务代码完成逻辑层的处理
  2. 通过数据传输接口(注册Page时的data属性及后续的setData方法调用)将逻辑层的数据传输给视图层。
  3. 视图层由WXML语言编写的模板通过“数据绑定”与逻辑层传输过来的数据merge成展现结果并展现
  4. 视图的样式控制由WXSS语言编写的样式规则进行配置

与Vue的区别

最大的区别就是,小程序并不是“正宗”的MVVM。在数据绑定上,它是单向绑定的。而vue是双向的。
如要实现一个提供一个输入框,并且把用户的输入同步显示到视图,如下图
vue
在vue中是这样实现的:

1
2
3
<div id="app">
{{ message }}
</div>

1
2
3
4
5
6
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})

在小程序中是这样实现的
1
2
3
4
<view class="section">
<view class="section__title">你输入的是:{{inputValue}}</view>
<input bindinput="bindKeyInput" placeholder="输入同步到view中"/>
</view>

1
2
3
4
5
6
7
8
9
10
Page({
data: {
inputValue: ''
},
bindKeyInput: function(e) {
this.setData({
inputValue: e.detail.value
})
}
})

因为,微信小程序的JS逻辑层与视图层分散在两个不同的上下文环境中(JS逻辑跑在JsCore中,视图层的渲染包括模板渲染、样式应用、事件派发却都在native环境中)。所以数据对象(view-model)在两层间没有共享,并且同步通信的成本太高。
因此,微信小程序在初始化之后,再对原来的数据对象进行任何更改,都始终不会生效,需要调用setData。以及,在事件冒泡的阻止上,微信小程序在监听时即决定是否阻止事件冒泡。

参考