第2章 小程序初体验
上一章我们成功地创建了第一个示例小程序——Hello WXapplet。本章通过解析这个小程序项目,使大家尽可能对小程序有个全局的认知,包括小程序的框架、目录结构、开发步骤以及入口界面、示例代码的使用与运行等。
2.1 理解小程序
对于用户而言,小程序的直观表现只是多个相互关联的页面。我们的小程序Hello WXapplet也一样,它由2个相互关联的页面构成:首页(index)与信息页(logs)。点击首页的头像就切换到信息页,在信息页点击“返回”可以从信息页返回到首页,如图2-1所示。
图2-1 两个相互关联的页面
小程序的开发实际上就是实现这些页面的展示(视图),以及实现“页面上用户交互事件”、“页面间切换逻辑”、“数据存储及网络调用”等事务与逻辑处理的过程。
2.1.1 Hello WXapplet项目目录及文件构成
我们先从文件目录结构上来了解Hello WXapplet项目的构成。点击开发者工具左侧导航的“编辑”,我们可以看到Hello WXapplet项目的目录结构及包含文件如图2-2所示。
图2-2 Hello WXapplet项目的目录结构
目录结构显示:小程序项目在创建时的目录(示例的本地开发目录为:“D:\小程序巧应用”)之下,包含3个app开头的文件(app.js、app.json、app.wxss)以及pages目录与utils目录。其中pages目录存放2个页面(index与logs)的构成文件。从示例中,我们看到:每个页面都是一个目录,目录名就是唯一的页面名,其下再由以页面名为前缀的2~4个文件组成。
对小程序的目录文件结构,我们可以归纳一下,如图2-3所示。
图2-3 小程序的目录文件结构
左侧3个app文件必须放在小程序根目录下,其他文件则由开发者自由控制。这3个文件说明如下:
■ app.js是小程序的脚本代码,用来监听并处理小程序的生命周期函数、声明全局变量。
■ app.json是对整个小程序的全局配置,配置小程序是由哪些页面组成,配置小程序的窗口背景色等。
■ app.wxss是整个小程序的公共样式表。
其中app.js和app.json是必需的。
小程序页面是由同路径下同名但不同后缀的2~4个文件组成:
■.js后缀的文件是脚本文件。
■.json后缀的文件是配置文件。
■.wxss后缀的是样式表文件。
■.wxml后缀的文件是页面结构文件。
其中.js与.wxml文件是必需的。
2.1.2 Hello WXapplet项目的代码实现
我们再从代码层面了解Hello WXapplet项目的实现,根据小程序的目录结构,代码实现有两大部分——小程序实例与页面,下面分别介绍。
1.小程序实例的代码实现
在Web开发者工具的“编辑”模式下,我们来看Hello WXapplet这个项目里的代码文件,最关键也必不可少的是app.js、app.json、app.wxss这三个文件,分别代表脚本文件、配置文件、样式表文件。微信小程序运行时会读取这些文件,并生成小程序实例。
app.js脚本代码用于监听并处理小程序的生命周期函数、声明全局变量、调用框架提供的丰富的API等。如本例app.js文件中,我们调用了的同步存储及同步读取本地数据的API——wx.setStorageSync()及wx.getStorageSync()。代码见程序清单2-1。想了解更多可用API,可参考本书第5章“API接口的开发应用”。
程序清单2-1 小程序app.js
// app.js App({ onLaunch: function () { // 调用API从本地缓存中获取数据 var logs = wx.getStorageSync('logs') || [] logs.unshift(Date.now()) wx.setStorageSync('logs', logs) }, getUserInfo:function(cb){ var that = this; if(this.globalData.userInfo){ typeof cb == "function" && cb(this.globalData.userInfo) }else{ // 调用登录接口 wx.login({ success: function () { wx.getUserInfo({ success: function (res) { that.globalData.userInfo = res.userInfo; typeof cb == "function" && cb(that.globalData.userInfo) } }) } }); } }, globalData:{ userInfo:null } })
app.json配置文件是对整个小程序的全局配置,代码见程序清单2-2。开发者将在这个文件中配置小程序是由哪些页面组成、配置小程序的窗口背景色、配置导航条样式、配置默认标题等。
注意 app.json不可添加任何注释。
更多关于小程序的全局配置项可参考本书3.1节。
程序清单2-2 小程序app.json
{ "pages":[ "pages/index/index", "pages/logs/logs" ], "window":{ "backgroundTextStyle":"light", "navigationBarBackgroundColor": "#fff", "navigationBarTitleText": "WeChat", "navigationBarTextStyle":"black" } }
app.wxss样式表文件是整个小程序的公共样式表,代码见程序清单2-3。我们可以在页面“组件”的class属性上直接使用app.wxss中声明的样式规则。
关于.wxss文件中的样式规则可参考本书3.3.2节“wxss详解”。
程序清单2-3 小程序app.wxss
/**app.wxss**/ .container { height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: space-between; padding: 200rpx 0; box-sizing: border-box; }
2.小程序页面的代码实现
在我们创建的Hello WXapplet小程序项目中,包含两个页面——index页面和logs页面,即首页和小程序启动日志的展示信息页,它们都在pages目录下。
每一个小程序页面可由同路径下同名的2~4个不同后缀文件组成,如:Hello WXapplet小程序的index页面就由pages目录下index路径中index.js、index.wxml、index.wxss、index.json四个文件组成,它们分别是页面脚本文件、页面结构文件、页面样式表文件、页面配置文件。其中,.wxml与.js文件是页面所必需的,而.wxss与.json文件则是可选的。
注意 微信小程序中的每一个页面的“路径+页面名”都需要写在app.json的pages中,且pages中的第一个页面是小程序的首页。.wxml文件与.wxss文件作为小程序开发框架的一部分,我们在第3章会详细介绍。
下面分别介绍index页面与logs页面。
index.wxml是页面的结构文件,代码见程序清单2-4。
程序清单2-4 页面结构index.wxml
<! --index.wxml--> <view class="container"> <view bindtap="bindViewTap" class="userinfo"> <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size= "cover"></image> <text class="userinfo-nickname">{{userInfo.nickName}}</text> </view> <view class="usermotto"> <text class="user-motto">{{motto}}</text> </view> </view>
index.wxml文件中使用了<view/>、<image/>、<text/>这三个组件来搭建页面结构,绑定数据和交互处理函数。有关页面组件的详细使用可以参考本书第4章。
index.js是页面的脚本文件,代码见程序清单2-5。我们在这个文件中监听并处理页面的生命周期函数~onLoad(),获取小程序实例~getApp(),声明并处理数据,响应页面交互事件等。
程序清单2-5 页面脚本index.js
// index.js // 获取应用实例 var app = getApp() Page({ data: { motto: 'Hello World', userInfo: {} }, // 事件处理函数 bindViewTap: function() { wx.navigateTo({ url: '../logs/logs' }) }, onLoad: function () { console.log('onLoad') var that = this // 调用应用实例的方法获取全局数据 app.getUserInfo(function(userInfo){ // 更新数据 that.setData({ userInfo:userInfo }) }) } })
从上面的代码我们可以知道,.js文件是页面逻辑处理层。详细的逻辑层编码请参考本书3.2节。
index.wxss是页面的样式表文件,代码见程序清单2-6。
程序清单2-6 页面样式index.wxss
// index.wxss .userinfo { display: flex; flex-direction: column; align-items: center; } .userinfo-avatar { width: 128rpx; height: 128rpx; margin: 20rpx; border-radius: 50%; } .userinfo-nickname { color: #aaa; } .usermotto { margin-top: 200px; }
页面的样式表文件是非必要的。当页面有样式表文件时,文件中的样式规则会层叠覆盖app.wxss中的样式规则。否则,即使没有页面样式表文件,我们也可以在页面的结构文件中直接使用app.wxss中指定的样式规则。
index.json是页面的配置文件。页面的配置文件同样是非必要的。当页面有配置文件时,文件中的配置项在该页面上会覆盖app.json的window中相同的配置项。若没有指定页面的配置文件,则在该页面直接使用app.json中的默认配置项。更多配置文件编写与解析,可参考本书3.1节。
接下来我们再看看logs页面。logs.wxml是logs页面的结构文件,代码见程序清单2-7。
程序清单2-7 页面结构logs.wxml
<! --logs.wxml--> <view class="container log-list"> <block wx:for="{{logs}}" wx:for-item="log"> <text class="log-item">{{index + 1}}. {{log}}</text> </block> </view>
logs页面使用<block/>控制标签来组织代码,在<block/>上使用控制属性wx:for绑定logs数据,并将logs数据循环展开节点。
注意 上述代码中的<block/>并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性(如wx:for或wx:if)。
logs.js是logs页面的脚本文件,代码见程序清单2-8。
程序清单2-8 页面脚本logs.js
// logs.js var util = require('../../utils/util.js') Page({ data: { logs: [] }, onLoad: function () { this.setData({ logs: (wx.getStorageSync('logs') || []).map(function (log) { return util.formatTime(new Date(log)) }) }) } })
上述脚本文件代码中,使用了require()来引入模块化.js脚本文件。关于模块化代码,可参考本书3.2.3节。