一.小程序框架介绍
小程序框架包含小程序的配置、框架接口、场景值、WXML 和 WXS等。
二.小程序的配置
小程序的配置分为全局配置、页面配置以及sitemap配置。
1.全局配置
小程序根目录下的 app.json
文件用来对微信小程序进行全局配置。文件内容为一个JSON
对象,有以下属性:
属性 | 类型 | 必填 | 描述 |
---|---|---|---|
entryPagePath | string | 否 | 小程序默认启动首页 |
pages | string[] | 是 | 页面路径列表 |
window | Object | 否 | 全局的默认窗口表现 |
… | … | … | … |
1.entryPagePath
指定小程序的默认启动路径(首页)。如果不填,将默认为 pages
列表的第一项。
{
"entryPagePath": "pages/index/index"
}
2.pages
包含了小程序所包含的全部页面以及路径。当我们需要新增加一个页面时,有以下几种方法:
- 在pages列表中直接添加路径,系统会自动在pages文件夹下新建对应的页面文件。
- 右键pages文件夹新建一个文件夹user,然后右键user选择新建page
"pages": [
"pages/index/index",
"pages/home/home",
"pages/kind/kind",
"pages/cart/cart",
"pages/logs/logs"
],
小程序中新增/减少页面,都需要对 pages 数组进行修改。
注意,当需要改变首页时,直接在pages列表中按住Alt键通过上移下移键即可直接移动。
3.window
用于设置小程序的状态栏、导航条、标题、窗口背景色。
对于pageOrientation
屏幕样式这个属性:
默认值为portrait
,即竖屏显示。
auto
:在屏幕旋转时,这个页面将随之旋转,显示区域尺寸也会随着屏幕旋转而变化。
landscape
:固定为横屏显示。
"window": {
"navigationBarBackgroundColor": "#0094ff",
"navigationBarTitleText": "嗨购",
"navigationBarTextStyle": "white",
"backgroundColor": "#efefef",
"backgroundTextStyle": "dark",
"enablePullDownRefresh": true,
"onReachBottomDistance": 50,
"pageOrientation": "auto"
},
注意,对于IOS手机,属性
backgroundColor
要替换成backgroundColorTop
和backgroundColorBottom
,因此在单独页面的配置文件中如果想要替换全局配置也要改成backgroundColorTop
。
4.tabBar
如果小程序是一个多tab
应用(客户端窗口的底部或顶部有 tab 栏可以切换页面),可以通过tabBar
配置项指定tab
栏的表现,以及tab 切换时显示的对应页面。
注意,配置tabBar时尽量要做到首尾呼应(要和头部的颜色保持一致保证美观度)。另外,如果你想要将菜单栏放在顶部,那么可以添加
"position":"top"
,但是这样的话图标就不会显示了。
tabBa
r中底部菜单栏的图标是图片格式,可以去阿里图标库下载,编写小程序下载png时大小选择81即可。
"tabBar": {
"color": "#000",
"selectedColor": "#0094ff",
"backgroundColor": "#efefef",
"borderStyle": "white",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "icons/shouye.png",
"selectedIconPath": "icons/shouye_active.png"
},
{
"pagePath": "pages/kind/kind",
"text": "分类",
"iconPath": "icons/fenlei.png",
"selectedIconPath": "icons/fenlei_active.png"
},
{
"pagePath": "pages/cart/cart",
"text": "购物车",
"iconPath": "icons/gouwuche.png",
"selectedIconPath": "icons/gouwuche_active.png"
},
{
"pagePath": "pages/user/user",
"text": "我的",
"iconPath": "icons/wode.png",
"selectedIconPath": "icons/wode_active.png"
}
],
"style": "v2",
"sitemapLocation": "sitemap.json"
},
5.networkTimeout
各类网络请求的超时时间,单位均为毫秒。
6.debug
可以在开发者工具中开启 debug
模式,在开发者工具的控制台面板,调试信息以 info
的形式给出,其信息有Page
的注册,页面路由,数据更新,事件触发等。可以帮助开发者快速定位一些常见的问题。
7.functionalPages
插件所有者小程序需要设置这一项来启用插件功能页
8.subpackages
启用分包加载时,声明项目分包结构。
9.workers
使用 Worker 处理多线程任务时,设置 Worker
代码放置的目录。
10.requiredBackgroundModes
申明需要后台运行的能力,类型为数组。目前支持以下项目:
audio
: 后台音乐播放location
: 后台定位
{
"pages": ["pages/index/index"],
"requiredBackgroundModes": ["audio", "location"]
}
11.plugins
声明小程序需要使用的插件。
12.preloadRule
声明分包预下载的规则。
13.resizable
在 iPad 上运行的小程序可以设置支持屏幕旋转。
在 PC 上运行的小程序,用户可以按照任意比例拖动窗口大小,也可以在小程序菜单中最大化窗口
14.usingComponents
在此处声明的自定义组件视为全局自定义组件,在小程序内的页面或自定义组件中可以直接使用而无需再声明。
15.permission
小程序接口权限相关设置。字段类型为 Object
。
"permission": {
"scope.userLocation": {
"desc": "你的位置信息将用于小程序位置接口的效果展示"
}
}
16.sitemapLocation
指明 sitemap.json 的位置;默认为 ‘sitemap.json’ 即在 app.json 同级目录下名字的 sitemap.json
文件。文件内部大致规定了小程序能否被微信搜索以及哪些页面能够被搜索到。
17.style
微信客户端 7.0 开始,UI 界面进行了大改版。小程序也进行了基础组件的样式升级。app.json 中配置 "style": "v2"
可表明启用新版的组件样式。
18.useExtendedLib
指定需要引用的扩展库。目前支持以下项目:
指定后,相当于引入了对应扩展库相关的最新版本的 npm 包,同时也不占用小程序的包体积。rc工具版本支持分包引用。用法如下:
{
"useExtendedLib": {
"kbone": true,
"weui": true
}
}
19.entranceDeclare
聊天位置消息用打车类小程序打开。
"entranceDeclare": {
"locationMessage": {
"path": "pages/index/index",
"query": "foo=bar"
}
}
20.darkmode
可通过配置"darkmode": true
表示当前小程序可适配DarkMode
,所有基础组件均会根据系统主题展示不同的默认样式,navigation bar
和 tab bar
也会根据开发者的配置自动切换。
配置后,请根据DarkMode 适配指南自行完成基础样式以外的适配工作。
{
"darkmode": true
}
21.themeLocation
自定义 theme.json 的路径,当配置"darkmode":true
时,当前配置文件为必填项。
{
"themeLocation": "/path/to/theme.json"
}
22.lazyCodeLoading
通常情况下,在小程序启动期间,所有页面及自定义组件的代码都会进行注入,当前页面没有使用到的自定义组件和页面在注入后其实并没有被使用。
自基础库版本 2.11.1 起,小程序支持有选择地注入必要的代码,以降低小程序的启动时间和运行时内存。
{
"lazyCodeLoading": "requiredComponents"
}
当配置了这一项时,小程序仅注入当前页面需要的自定义组件和页面代码,在页面中必然不会用到的自定义组件不会被加载和初始化。
注意:添加这项配置后,未使用到的代码文件将不被执行。
23.singlePage
单页模式相关配置
24.navigateToMinProgramAppIdList
当小程序需要使用 wx.navigateToMiniProgram
接口跳转到其他小程序时,需要先在配置文件中声明需要跳转的小程序appId列表,最多允许填写10个。
"navigateToMinProgramAppIdList" : [
"...",
"..."
]
2.页面配置
每一个小程序页面也可以使用 .json
文件来对本页面的窗口表现进行配置。页面中配置项在当前页面会覆盖 app.json
的 window
中相同的配置项。文件内容为一个JSON
对象。
页面配置其实和全局配置差不多,如果配置了和全局一样的属性那么就会覆盖全局属性,更换效果。
3.sitemap配置
小程序根目录下的 sitemap.json
文件用于配置小程序及其页面是否允许被微信索引,文件内容为一个JSON
对象,如果没有 sitemap.json
,则默认为所有页面都允许被索引。
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}
三.小程序框架接口
1.小程序APP
1.App(Object object)
注册小程序。接受一个Object
参数,其指定小程序的生命周期回调等。
App() 用于注册小程序,必须在app.js
中调用,必须调用且只能调用一次。不然会出现无法预期的后果。
//app.js
App({
onLaunch: function () {
// 展示本地存储能力
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
this.globalData.userInfo = res.userInfo
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
},
globalData: {
userInfo: null
}
})
2.AppObject getApp(Object object)
获取到小程序全局唯一的App
实例,在页面的JS文件中获取。
//index.js
//获取应用实例
const app = getApp()
console.log(app)
2.页面
1.Page(Object object)
注册小程序中的一个页面。接受一个Object
类型参数,其指定页面的初始数据、生命周期回调、事件处理函数等。
// pages/kind/kind.js
Page({
/**
* 页面的初始数据
*/
data: {
},
/**
* 生命周期函数--监听页面加载------请求数据
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
//页面相关事件处理函数---监听用户下拉刷新事件(重新请求了第一页的页面数据)
onPullDownRefresh: function() {
console.log("刷新了当前页面")
},
//上拉触底事件函数
/**
* 上拉加载---分页效果
*/
onReachBottom: function() {
console.log("对不起已经到底了")
},
/**
* 用户点击右上角的分享按钮
* 可以通过微信提供的api修改分享的内容
*/
onShareAppMessage: function() {
console.log("你准备好分享了吗")
},
/**
* 页面滚动事件的处理函数
* 默认的参数就是滚动条距离顶部的距离 --- 可以写成options
* 应用:滚动到某一个位置,返回顶部的按钮
*/
onPageScroll (event) {
console.log("页面正在滚动")
console.log(event)
},
/**
* 当前是 tab 页时,点击 tab 时触发
* tab就是全局配置时的底部菜单栏
*/
onTabItemTap () {
console.log("首页")
},
})
小程序加载时的执行顺序为:onLoad,onShiw,onReady。
2.getCurrentPages()
PageObject[] getCurrentPages()
:
获取当前页面栈。数组中第一个元素为首页,最后一个元素为当前页面。
注意:
- 不要尝试修改页面栈,会导致路由以及页面状态错误。
- 不要在
App.onLaunch
的时候调用getCurrentPages()
,此时page
还没有生成。
3.自定义组件
1.Component(Object object)
创建自定义组件,接受一个Object
类型的参数。
步骤:新建一个文件夹components
存放所有组件,然后再新建一个文件夹存放某个特定的组件(一般一个组件单独存放在一个文件夹中,便于管理),接着新建Components
就会得到对应的四个文件(wxml,wxss,js,json
),json
文件中相比于页面多了一条语句:
"component": true,
这条语句就指明了当前文件是一个组件。
接着在需要显示组件的页面的JSON文件中写入:
"usingComponents": {
//prolist一般就是组件名,后面跟上绝对路径
"prolist": "/components/prolist/prolist"
}
完事之后在可以在原页面使用标签的形式将组件给添加到页面中去:
<prolist></prolist>
// <prolist /> 单标签的形式也可以
注意,如果在原页面有css样式的需要重新**剪切到组件对应的css样式文件(prolist.wxss)**中去。
组件其实就是包含了视图的模块。
至此为止完成了自定义组件以及使用。
4.模块化
建议使用es6
的模块化方法,api中提供的是基于commonjs
规范的exports
以及require
语法。
1.定义工具模块 utils/index.js
数据请求模块以及可消失的提示框模块 - 暴露。
const baseUrl = 'http://daxun.kuboy.top'
/**
* 数据请求模块
* 接口地址 http://daxun.kuboy.top/apidoc
* 先显示加载框,然后请求结束加载框消失
*
*/
export function request (url, data) {
// 显示加载中
// 参考https://developers.weixin.qq.com/miniprogram/dev/api/ui/interaction/wx.showLoading.html
wx.showLoading({
title: '加载中',
})
// 使用promise 解决异步操作问题,此处还可以使用 async + await
return new Promise((resolve, reject) => {
// 微信小程序的数据请求方法
// 必须配置小程序的安全域名,
// 在开发阶段可以在“详情” - “本地设置” - 勾选中 不校验请求域名、web-view(业务域名)、TLS版本及HTTPS证书
wx.request({
url: baseUrl + url,
data: data || {},
success: (res) => {
// 隐藏加载中
wx.hideLoading();
// 后续处理
resolve(res.data)
},
// 异步操作执行失败的操作
fail : (err) => {
reject(err)
}
})
})
}
/**
* 可消失的提示框 - 默认只显示文字
* str 提示内容
* icon 是否需要图标,none 、 success(默认值) 、 loading
*/
export function Toast (str, icon) {
// 微信提供的API接口
// 参照 https://developers.weixin.qq.com/miniprogram/dev/api/ui/interaction/wx.showToast.html
wx.showToast({
title: str,
icon: icon || 'none'
})
}
2.在首页中测试
在首页的index.js
中的onLoad
函数中进行数据的请求:
// 请求数据
request({
url : '/pro',
data : {}
}).then((res) => { //then是请求成功后的处理方法
console.log(res)
}).catch((err) => { //catch是请求失败后的处理方法
console.log(err)
})
四.WXML语法
新建一个测试页面:pages/test/test
,但是在tabBar中并没有路由链接到新的测试页面。
解决方法:在普通编译处选择添加编译模式,然后选择新建页面的路径pages/test/test
,点击完成即可直接编译出新建的页面,省去了路由链接的环节。
1.数据绑定
1.简单绑定
WXML中的动态数据均来自对应Page的data。
Page({
data: {
message: 'Hello MINA!'
}
})
对应的WXML中显示数据的语法为:{{}}
<view> {{ message }} </view>
2.组件属性
小程序对于组件标签的属性绑定其实就是将vue
和react
二者相结合。
<!-- vue 绑定属性 :class="message" -->
<!-- react 绑定属性 class={message} -->
<view class="{{message}}">
组件属性
</view>
3.控制属性
data: {
message: "hello world",
flag: true
},
<!-- 控制属性 -->
<!-- vue v-if="flag" -->
<!-- wx:if wx:elif wx:else -->
<view wx:if="{{ flag }}">
如果flag为真我就显示
</view>
4.boolean以及number数据类型
如果数据类型是booblean
或者number
类型的数据,需要使用```{{}}````包裹。
<checkbox checked="{{ flag }}"></checkbox> //被选中
<checkbox checked="true"></checkbox> //被选中
<checkbox checked="false"></checkbox> //被选中,说明false单独写在双引号中是没用的
<checkbox checked="{{ !flag }}"></checkbox> //未被选中
5.表达式
表达式运算 可以在{{}}
内进行简单的运算,支持三元运算、算数运算、逻辑判断、字符串运算等。
data: {
message: "hello world",
flag: true,
number:30,
a:1,
b:10,
c:100,
len:15,
name: "curry"
},
<!-- 表达式 -->
<view>{{ 1 + 2 + 3 }}</view>
<!-- 下面的表达式未被解析,微信小程序不太支持js -->
<view>{{ message.split('').reverse().join('') }}</view>
<view test="{{flag ? true : false}}"> 属性 </view>
<view> {{a + b}} + {{c}} + d </view>
<view wx:if="{{len > 5}}">Steph Curry</view>
<view>{{"hello" + name}}</view>
2.列表渲染
1.单层循环
list:[
"库里",
"汤普森",
"杜兰特",
"格林",
"伊戈达拉"
]
在wx:for="{{ list }}"
中仅需指明循环的数据来源即可,不需要声明元素名item
以及索引值index
:
<!-- 一层循环 -->
<view wx:for="{{ list }}" wx:key="index">
<text>{{ index }}</text>---<text>{{ item }}</text>
</view>
2.双层循环
carlist:[
{
brand: "宝马",
typelist: ['x5','x6']
},
{
brand: "奔驰",
typelist: ['A4','Q7']
}
]
<!-- 两层循环
wx:for-item="itm" --- 重新指定元素名
wx:for-item="idx" --- 重新指定索引值
-->
<view wx:for="{{ carlist }}">
{{ brand }}
//为了避免混淆两层循环中的元素名item,可以重新命名
<view wx:for="{{item}}" wx:for-item="itm" wx:for-index="idx" wx:key="idx">
<view>{{ itm }}</view>
</view>
</view>
注意,不管是单层循环还是双层循环,都不能忘记加上
wx:key
关键字,里面的值如果没有指定那就填索引值index
。注意,之前wx:key
关键字的写法是wx:key="{{ index }}"
,但是后面更新过一次,如果有报错信息那就去掉双括号:wx:key="index"
3.条件渲染
wx:if
在框架中,使用wx:if=""
来判断是否需要渲染该代码块:
<view wx:if="{{flag}}"> True </view>
也可以用wx:elif
和wx:else
来添加一个else
块:
<view wx:if="{{len > 5}}"> 1 </view>
<view wx:elif="{{len > 2}}"> 2 </view>
<view wx:else> 3 </view>
因为wx:if
是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个<block/>
标签将多个组件包装起来,并在上边使用wx:if
控制属性:
<block wx:if="{{true}}">
<view> view1 </view>
<view> view2 </view>
</block>
注意:
<block/>
并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
wx:if vs hidden — (对比vue中的v-if与v-show
)
因为
wx:if
之中的模板也可能包含数据绑定,所以当wx:if
的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。同时
wx:if
也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。相比之下,hidden就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。
一般来说
wx:if
有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则wx:if
较好。
四.WXS语法
**WXS(WeiXin Script)**是小程序的一套脚本语言,结合WXML,可以构建出页面的结构。
WXS 与 JavaScript 是不同的语言,有自己的语法,并不和JavaScript一致。
熟悉js语法的可以很快速的接收并且掌握它。
五.WXSS语法
WXSS (WeiXin Style Sheets)是一套样式语言(CSS),用于描述WXML的组件样式。
WXSS 用来决定WXML的组件应该怎么显示。
为了适应广大的前端开发者,WXSS具有CSS大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
与 CSS 相比,WXSS 扩展的特性有:
-
尺寸单位
-
样式导入
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 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况
2.样式导入
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束
3.全局样式与局部样式
WXSS具有CSS大部分特性。同时为了更适合开发微信小程序,WXSS 对 CSS 进行了扩充以及修改。
与 CSS 相比,WXSS 扩展的特性有:
-
尺寸单位
-
样式导入
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 作为视觉稿的标准。
注意: 在较小的屏幕上不可避免的会有一些毛刺,请在开发时尽量避免这种情况
2.样式导入
使用@import
语句可以导入外联样式表,@import
后跟需要导入的外联样式表的相对路径,用;
表示语句结束
3.全局样式与局部样式
定义在app.wxss
中的样式为全局样式,作用于每一个页面。在pag
的wxss
文件中定义的*样式为局部样式,只作用在对应的页面,并会覆盖app.wxss
中相同的选择器(局部样式会覆盖全局样式)。