最近凑热闹试着开发微信的小程序, 从开始到入坑再到放弃, 写个博客以示纪念
1. 目录结构
├─pages
│ ├─index
│ │ ├─index.wxml
│ │ ├─index.wxss
│ │ └─index.js
│ └─logs
├─template
│ ├─template.wxml
│ ├─template.js
│ └─template.wxss
├─app.json
├─app.wxss
└─app.js
小程序的每一个界面的主要呈现是"page", 相当于安卓中的"Activity". 在小程序的根目录下的 app.xml app.wxss app.json
是整个小程序的公共文件.
其中:
app.json
是小程序配置文件 ( 相当于apk中的 AndroidManifest
);
app.wxss
是全局样式表, app.js
是全局js.
2. 配置文件
全局配置文件 app.json
记录了整个小程序的配置, 小程序中每一个能够呈现的页面 (Page) 都需要在 app.json 中注册 , app.json 也可以配置小程序的窗口(Window 包括了小程序页面上面的导航栏)样式
app.json
文件的语法是 json
语法, 文件中中使用一个 key
为pages 的数组来记录页面, 使用 key
为window 的数组保存小程序的窗口配置
{
"pages":[
"pages/index/index",
"pages/active/active",
"pages/details/details",
"pages/search/search",
"pages/cashier/cashier",
"pages/checkout/checkout",
"pages/status/status"
],
"window":{
"navigationBarBackgroundColor": "#00aaff",
"navigationBarTitleText" : "一个Demo",
"navigationBarTextStyle":"#fff",
"enablePullDownRefresh" : false
}
}
3. 布局文件 wxml
wxml
是微信小程序的布局文件的后缀名, 其本质上是一个xml文件( 类似 apk 的布局文件 xml). 可以使用微信小程序提供的 组件库 来组建布局.
在微信小程序中, 页面布局中的数据是可以动态指定的. 为页面设置数据的方法是数据绑定, 而不是像web中那样使用DOM对象来动态设置. (*微信小程序中没有DOM对象.)
在wxml中可以使用 Mustache 语法(双大括号)
来实现绑定数据/动态渲染的功能. 查看微信小程序文档
<view>{{viewData}}</view>
<!--这个view显示的内容是由变量viewData指定-->
<view wx:if={{ifDisplay}}/>
<!--这个view的显示与否由ifDisplay变量指定-->
<block wx:for={{list}} wx:for-item="item" wx:key="index">
<view>{{item.data}}</view>
</block>
<!--循环遍历list, 将list中每一个item的name值作为元素<view>的值, 总共渲染list.length个<view> -->
<!-- 注意, block标签只是一个块级标记而已, 实际显示时并不会渲染block>
4. JavaScript
微信小程序中的JavaScript脚本采用标准的JavaScript语法, 支持ES6, 不支持jQuery库.
JavaScript脚本负责数据绑定/逻辑处理/事件处理
每个page的js脚本都要有一个Page( Object)
函数, 在页面(page)中使用到的所有的函数和数据都作为page函数参数(Object对象)的 key:value
键值对在Page()函数里注册.
微信小程序框架里包含了小程序的生命周期函数以及一些事件函数, 可以通过重写这些函数来实现一些功能(比如启动加载/下拉刷新/上拉加载等). 查看微信小程序文档
var app = getApp();
Page( {
data : {
data1: '',
data2: [],
data3: 0
},
onReady : function( ) {
//TODO
},
onShow : function() {
//TODO
},
onPullDownRefresh: function() {
//TODO
}
myFunction : function( e ) {
//TODO
//必须使用page的setData()函数才能将变化的数据重新绑定到页面上, 直接修改page.data属性会造成数据和页面显示不一致的错误
this.setData({
data2: [1, 2, 3]
});
},
});
5. WXSS
wxss文件的本质是css文件, 使用标准的css语法, 使用时按照css的标准即可.
6. 自定义组件(view)
微信小程序中自定义view相比于安卓是很不舒服的一种体验. 实现自定义view需要设计view的界面/数据和逻辑驱动
- view的数据: 使用wxml定义模板, 模板可以实现类似于自定义view的功能. 使用
<template>
标签来指定或者使用一个模板, 可以通过设置 <template>
标签的data属性. 例如:
<!--定义一个template-->
<template name="list-view">
<scroll-view>
<block wx:for={{list}}>
<view>{{item}}</view>
</block>
</scroll-view>
</template>
<!--使用这个template并绑定数据-->
<template is="list-view" data="{{list}}"/>
注意, 在使用模板前需要在 wxml 文件里先使用 <import>
标签导入模板的wxml文件.
- view的界面: 可以使用WXSS来控制view的渲染. 注意渲染时的类选择器的类名不要和page中的类名冲突. 在需要渲染自定义的view的wxss中使用
@import "../customed-view.wxss";
来导入自定义view的wxss文件. - view的逻辑驱动: 使用js文件来实现逻辑驱动. 应该设置命名空间以防止js中变量名的冲突. 可以使用模块化的设计来实现自定view的逻辑驱动的封装.
7. 模块化
模块化在微信小程序的官方文档里有详细的介绍, 微信小程序的模块化和node中的模块化用法类似, node中每一个js文件都是一个模块, 使用 require ('path');
获得模块的实例. require函数的返回值是一个js module的module.exports
对象的引用, 因此:
/*向module.exports中添加属性
** require返回: {name: 'chaol'}
*/
module.exports.name = 'chaol';
/*将module.exports指向一个对象
**require返回: {name: 'object'}
*/
module.exports = {name: 'object'};
8. 实现一个tab切换功能
这是我从书上看到的一个tab栏切换页面的实现方案, 将它的大致的思路记录下来.
- 实现tab-view 1.定义tab-view模板
<!--wxml-->
<template name="tab-view" class="tab-container">
<view class="tab-container" bindtop="onTabClicked">
<block wx:for="{{pages}}" wx:key="index" wx:for-item="item">
<text class="tab-button" data-index="{{index}}">{{item.name}}</text>
</block>
</view>
</template>
//wxss
.tab-container{
width: 100%;
display: flex;
}
- 在页面中引用tab-view
<!--wxml文件-->
<import "../View/tab-view.wxml"/>
<template is="{{currentPage.page}}" data="{{pageData}}"/>
<template is="tab-view" data="{{pages}}"/>
//wxss文件
@import "../View/tab-view.wxss"
//js文件
var page1=require("../template/page1.js"),
page1=require("../template/page2.js"),
page3=require("../template/page3.js");
Page([
data: {
currentPage: {name: 页面1, page: "page1", obj: page1},
pages :[{name: "页面1", page: "page1", obj: page1},
{name: "页面2", page: "page2", obj: page2},
{name: "页面3", page: "page3", obj: page3}]
},
//TODO
onTabClicked: function(event){
var index=event.currentTarget.dataset.index;
this.setData({currentPage: this.data.pages[index]});
//在这里还需要实现页面业务逻辑和页面数据的合并
//TODO
}
]);
- 实现切换
- 定义页面
<!--page1.wxml-->
<template name="page1">
<view>{{page1Text}}</view>
</template>
- 业务逻辑和页面数据合并
//...此处衔接以上js
onTabClicked: function(event){
var index=event.currentTarget.dataset.index;
this.setData({currentPage: this.data.pages[index].page});
this.bindFunAndData(this, this.data.pages[index].obj);
},
bindFunAndData: function(currentPage, targetPage){
var p;
for ( p in targetPage ) {
currentPage[p] = targetPage[p]
}
}
大致就到这里了. 包括网络请求和传感器在内的API都可以在微信小程序官方文档里查到.
注意:
1. 直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致。
2. 单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。
3. 请不要把 data 中任何一项的 value 设为 undefined ,否则这一项将不被设置并可能遗留一些潜在问题.
4. 微信小程序的页面在渲染时需要转换成HTML并由系统的webview进行渲染, 所以应尽量减少页面的重绘, 页面需要更新时尽量使用```setData()```
我的水平有限, 如若读者发现文中错误还望不吝指出, 感激不尽!