Fork me on GitHub

微信小程序开发文档总结

小程序开发文档的简要概括。

基本的文件结构

最关键也是必不可少的,是 app.js、app.json、app.wxss 这三个,.js后缀的是脚本文件,.json后缀的文件是配置文件,.wxss后缀的是样式表文件。

app.js: 是小程序的脚本代码。我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。 调用框架提供的丰富的 API,如本例的同步存储及同步读取本地数据。

app.json: 对整个小程序的全局配置。可以在这个文件中配置小程序是由哪些页面("pages")组成,配置小程序的窗口("window")背景色,配置导航条样式,配置默认标题。注意该文件不可添加任何注释。

app.wxss: 整个小程序的公共样式表。我们可以在页面组件的 class 属性上直接使用 app.wxss 中声明的样式规则。

创建页面

小程序的页面都在根目录下的pages文件目录,例如一开始的示例程序中(有展示用户头像的欢迎页和小程序启动日志展示页),这两个页面都在pages目录下,即pages/index/pages/logs/

微信小程序中的每一个页面的【路径+页面名】都需要写在 app.json 的 "pages" 中,且 "pages" 中的第一个页面是小程序的首页。

1
2
3
4
"pages":[
"pages/index/index",
"pages/logs/logs"
],

每一个小程序页面是由同路径下同名的四个不同后缀文件的组成,如:index.js(脚本)、 index.wxml(页面结构)、 index.wxss(样式表)、 index.json(配置)。

  • index.wxml 是页面的结构文件。

  • index.js 是页面的脚本文件,在这个文件中我们可以监听并处理页面的生命周期函数、获取小程序实例,声明并处理数据,响应页面交互事件等。

  • index.wxss 是页面的样式表。 页面的样式表是非必要的。当有页面样式表时,页面的样式表中的样式规则会层叠覆盖 app.wxss 中的样式规则。如果不指定页面的样式表,也可以在页面的结构文件中直接使用 app.wxss 中指定的样式规则。

注意微信小程序开发中使用了新的尺寸单位,rpx(responsive pixel),可以根据屏幕宽度自适应,规定屏幕宽度为750rpx。

如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。微信官方建议视觉稿以iPhone 6为标准。(补充rem: 规定屏幕宽度为20rem,所以1rem=750/20 rpx)

  • index.json 是页面的配置文件。 页面的配置文件是非必要的。当有页面的配置文件时,配置项在该页面会覆盖 app.json 的 window 中相同的配置项。如果没有指定的页面配置文件,则在该页面直接使用 app.json 中的默认配置。

文件目录安排如下所示如下图所示。
小程序基本的目录结构

框架

框架提供了自己的视图层描述语言WXML和WXSS,以及基于JavaScript的逻辑层框架,并在视图层与逻辑层间提供了数据传输和事件系统,可以让开发者可以方便的聚焦于数据与逻辑上。

  • 响应的数据绑定

框架的核心是一个响应的数据绑定系统。整个系统分为两块视图层(View)和逻辑层(App Service)。框架可以让数据与视图非常简单地保持同步。当做数据修改的时候,只需要在逻辑层修改数据,视图层就会做相应的更新。

  • 页面管理

框架管理了整个小程序的页面路由,可以做到页面间的无缝切换,并给以页面完整的生命周期。开发者需要做的只是将页面的数据,方法,生命周期函数注册进框架中,其他的一切复杂的操作都交由框架处理。

  • 基础组件

框架提供了一套基础的组件,这些组件自带微信风格的样式以及特殊的逻辑,开发者可以通过组合基础组件,创建出强大的微信小程序 。

  • 丰富的API

框架提供丰富的微信原生API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。

配置

使用app.json文件来对微信小程序进行全局配置,决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。app.json的配置项列表包括: pages window tabBar networkTimeout debug

pages :接受一个数组,每一项都是字符串,来指定小程序由哪些页面组成。每一项代表对应页面的【路径+文件名】信息,数组的第一项代表小程序的初始页面。小程序中新增/减少页面,都需要对 pages 数组进行修改。 文件名不需要写文件后缀,因为框架会自动去寻找路径.json,.js,.wxml,.wxss的四个文件进行整合。

window: 用于设置小程序的状态栏、导航条、标题、窗口背景色。具体参数如下:
window配置项参数

tabBar: 如果我们的小程序是一个多 tab 应用(客户端窗口的底部有tab栏可以切换页面),那么我们可以通过 tabBar 配置项指定 tab 栏的表现,以及 tab 切换时显示的对应页面。

page.json: 每一个小程序页面也可以使用.json文件来对本页面的窗口表现进行配置。页面的配置比app.json全局配置简单得多,只是设置 app.json 中的 window 配置项的内容,页面中配置项会覆盖 app.json 的 window 中相同的配置项。页面的.json只能设置window相关的配置项,以决定本页面的窗口表现,所以无需写window这个键。

逻辑层(APP Service)

小程序开发框架的逻辑层是由JavaScript编写。 逻辑层将数据进行处理后发送给视图层,同时接受视图层的事件反馈。 在javascript基础上,增加 App 和 Page 方法,进行程序和页面的注册; 提供丰富的 API,如扫一扫,支付等微信特有能力; 每个页面有独立的作用域,并提供模块化能力; 由于框架并非运行在浏览器中,所以 JavaScript 在 web 中一些能力都无法使用,如 document,window 等; 开发者写的所有代码最终将会打包成一份 JavaScript,并在小程序启动的时候运行,直到小程序销毁。类似 ServiceWorker,所以逻辑层也称之为 App Service。

注册程序

APP()

App()函数用来注册一个小程序。接受一个object参数,其指定小程序的生命周期函数等。
APP注册参数说明

前台、后台定义:当用户点击左上角关闭,或者按了设备 Home 键离开微信,小程序并没有直接销毁,而是进入了后台;当再次进入微信或再次打开小程序,又会从后台进入前台。需要注意的是:只有当小程序进入后台一定时间,或者系统资源占用过高,才会被真正的销毁。

关闭小程序(基础库版本1.1.0开始支持):当用户从扫一扫、转发等入口(场景值为1007, 1008, 1011, 1025)进入小程序,且没有置顶小程序的情况下退出,小程序会被销毁。小程序运行机制在基础库版本 1.4.0 有所改变:上一条关闭逻辑在新版本已不适用,。

getAPP()

提供了全局的getApp()函数,可以获取到小程序实例。

注意:App()必须在app.js中注册,且不能注册多个。

不要在定义于App()内的函数中调用getApp(),使用this就可以拿到app实例。

不要在onLaunch的时候调用getCurrentPage(),此时page还没有生成。

通过getApp()获取实例之后,不要私自调用生命周期函数。

场景值

场景值描述了开启小程序的来源,例如如果从发现栏小程序主入口开启,场景值为1001。可以在 App 的 onLaunch 和 onShow 中获取。

注册页面

Page()

Page() 函数用来注册一个页面。接受一个 object 参数,其指定页面的初始数据、生命周期函数、事件处理函数等。

页面注册参数说明

初始化数据 将作为页面的第一次渲染。data 将会以 JSON 的形式由逻辑层传至渲染层,所以其数据必须是可以转成 JSON 的格式:字符串,数字,布尔值,对象,数组。渲染层可以通过 WXML 对数据进行绑定。

Page.prototype.route  route字段可以获取到当前页面的路径。
Page.prototype.setData()  setData 函数用于将数据从逻辑层发送到视图层,同时改变对应的 this.data 的值。

setData() 参数格式: 接受一个对象,以 key,value 的形式表示将 this.data 中的 key 对应的值改变成 value。ey 可以非常灵活,以数据路径的形式给出,如 array[2].message,a.b.c.d,并且不需要在 this.data 中预先定义。

注意:

直接修改 this.data 而不调用 this.setData 是无法改变页面的状态的,还会造成数据不一致
单次设置的数据不能超过1024kB,请尽量避免一次设置过多的数据。

Page实例的生命周期

Page实例的生命周期

路由

页面路由:所有页面的路由全部由框架进行管理。

页面栈: 框架以栈的形式维护了当前的所有页面。当发生路由切换的时候,页面栈的表现如下:
路由与页面栈

getCurrentPages() 用于获取当前页面栈的实例,以数组形式按栈的顺序给出,第一个元素为首页,最后一个元素为当前页面。(注意;不要尝试修改页面栈,会导致路由以及页面状态错误。)

路由的触发方式

Tab切换对应的生命周期

navigateTo,redirectTo只能打开非 tabBar 页面。
switchTab 只能打开 tabBar 页面。
reLaunch 可以打开任意页面。
页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar。
调用页面路由带的参数可以在目标页面的onLoad中获取。

模块化

文件作用域:在JavaScript文件中声明的变量和函数只在该文件中有效;不同的文件中可以声明相同名字的变量和函数,不会互相影响。

通过全局函数getApp()可以获取全局的应用实例,如果需要全局的数据可以在App()中设置全局数据。

模块化: 将一些公共的代码抽离成为一个单独的js文件,作为一个模块。模块只有通过module.exports或者 exports才能对外暴露接口。​在需要使用这些模块的文件中,使用require(path)将公共代码引入(tips: require暂时不支持绝对路径)。

注意: exports是module.exports的一个引用,因此在模块里边随意更改exports的指向会造成未知的错误。所以我们更推荐开发者采用module.exports来暴露模块接口,除非你已经清晰知道这两者的关系。

视图层(View)

WXML

WXML(WeiXin Markup Language)是框架设计的一套标签语言,结合基础组件、事件系统,可以构建出页面的结构。

WXML具有数据绑定、列表渲染、条件渲染、模板、事件、引用等功能。

数据绑定

WXML中的动态数据均来自对应Page的 data对象中的数据。数据绑定使用 双大括号 将变量包起来。

(1)用于内容: <view> {{ message }} </view>

(2)组件属性(需要在双引号之内): <view id="item-{{id}}"> </view>

(3)控制属性(需要在双引号之间): <view wx:if="{{condition}}"> </view>

(4)关键字(需要在双引号之间): <checkbox checked="{{false}}"> </checkbox> 其中 false:boolean 类型的 false,代表假值。
注意: 特别注意:不要直接写 checked="false",其计算结果是一个字符串,转成 boolean 类型后代表真值。

(5)计算: 可以在{{}}内进行简单的运算。支持以下几种方式,

三元运算: <view hidden="{{flag ? true : false}}"> Hidden </view>

算数运算: view> {{a + b}} + {{c}} + d </view>

逻辑判断: <view wx:if="{{length > 5}}"> </view>

字符串运算: <view>{{"hello" + name}}</view>

数据路径运算: <view>{{object.key}} {{array[0]}}</view>

组合: 也可以在Mustache(双大括号)内直接进行组合,构成新的对象或者数组。

数组:<view wx:for-items="{{[zero, 1, 2, 3, 4]}}"> {{item}} </view>

Page({
  data: {
    zero: 0
  }
})

对象: <template is="objectCombine" data="{{for: a, bar: b}}"></template>, 最终组合成的对象是{for: 1, bar: 2}

Page({
  data: {
    a: 1,
    b: 2
  }
})

也可以用扩展运算符…来将一个对象展开,<template is="objectCombine" data="{{...obj1, ...obj2, e: 5}}"></template>,最终组合成的对象是{a: 1, b: 2, c: 3, d: 4, e: 5}

Page({
  data: {
    obj1: {
      a: 1,
      b: 2
    },
    obj2: {
      c: 3,
      d: 4
    }
  }
})

注意:注意:上述方式可以随意组合,但是如有存在变量名相同的情况,后边的会覆盖前面,如<template is="objectCombine" data="{{...obj1, ...obj2, a, c: 6}}"></template>,根据以下数据,最终组合成的对象是 {a: 5, b: 3, c: 6}

Page({
  data: {
    obj1: {
      a: 1,
      b: 2
    },
    obj2: {
      b: 3,
      c: 4
    },
    a: 5
  }
})

注意: 花括号和引号之间如果有空格,将最终被解析成为字符串,如下

<view wx:for="{{[1,2,3]}} ">
  {{item}}
</view>

等同于

<view wx:for="{{[1,2,3] + ' '}}">
  {{item}}
</view>

列表渲染

(1)wx:for

wx:for 在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item

<view wx:for="{{array}}">
  {{index}}: {{item.message}}
</view>

wx:for-item 指定数组当前元素的变量名。

wx:for-index 指定数组当前下标的变量名。

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName">
  {{idx}} {{itemName.message}}
</view>

wx:for 也可以嵌套,下边是一个九九乘法表:

1
2
3
4
5
6
7
<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}" wx:for-item="i">
<view wx:for="{{[1, 2, 3, 4, 5, 6, 7, 8, 9]}}" wx:for-item="j">
<view wx:if="{{i <= j}}">
{{i}} *{{j}} = {{i * j}}
</view>
</view>
</view>

(2)block wx:for

将 wx:for 用在<block/>标签上,以渲染一个包含多节点的结构块。

<block wx:for="{{[1, 2, 3]}}">
  <view> {{index}}: </view>
  <view> {{item}} </view>
</block>

(3)wx:key

如果列表中项目的位置会动态改变或者有新的项目添加到列表中,并且希望列表中的项目保持自己的特征和状态(如 <input/> 中的输入内容,<switch/> 的选中状态),需要使用 wx:key 来指定列表中项目的唯一的标识符

wx:key 的值以两种形式提供:

1.字符串,代表在 for 循环的 array 中 item 的某个 property,该 property 的值需要是列表中唯一的字符串或数字,且不能动态改变。
2.保留关键字 *this 代表在 for 循环中的 item 本身,这种表示需要 item 本身是一个唯一的字符串或者数字,如:

当数据改变触发渲染层重新渲染的时候,会校正带有 key 的组件,框架会确保他们被重新排序,而不是重新创建,以确保使组件保持自身的状态,并且提高列表渲染时的效率。

注意: 当 wx:for 的值为字符串时,会将字符串解析成字符串数组。

<view wx:for="array">
  {{item}}
</view>

等同于

<view wx:for="{{['a','r','r','a','y']}}">
  {{item}}
</view>

条件渲染

(1)wx:if

wx:if="{{condition}}"来判断是否需要渲染该代码块, <view wx:if="{{condition}}"> True </view>。也可以用wx:elifwx:else来添加一个else块:

<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>

(2)block wx:if

wx:if是一个控制属性,需要将它添加到一个标签上。如果想一次性判断多个组件标签,可以使用一个<block/>标签将多个组件包装起来,并在上边使用wx:if控制属性。

<block wx:if="{{true}}">
  <view> view1 </view>
  <view> view2 </view>
</block>

注意:<block/>并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。

wx:if vs hidden

因为wx:if之中的模板也可能包含数据绑定,所以当wx:if的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。同时wx:if也是惰性的,如果在初始渲染条件为false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。

相比之下,hidden就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。

一般来说,wx:if有更高的切换消耗而hidden有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用hidden更好,如果在运行时条件不大可能改变则wx:if较好。

模板

WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。 模板拥有自己的作用域,只能使用data传入的数据。

(1)定义模板:使用name属性,作为模板的名字,然后在<template/>内定义代码片段。如下:

<template name="msgItem">
  <view>
    <text> {{index}}: {{msg}} </text>
    <text> Time: {{time}} </text>
  </view>
</template>

(2)使用模板: 使用 is属性,声明需要使用的模板,然后将模板所需要的data传入。 <template is="msgItem" data="{{...item}}"/>

Page({
  data: {
    item: {
      index: 0,
      msg: 'this is a template',
      time: '2016-09-15'
    }
  }
})

is 属性可以使用Mustache语法,来动态决定具体需要渲染哪个模板。

<template name="odd">
  <view> odd </view>
</template>
<template name="even">
  <view> even </view>
</template>

<block wx:for="{{[1, 2, 3, 4, 5]}}">
    <template is="{item % 2 == 0 ? 'even' : 'odd'}}"/>
</block>

事件

什么是事件:
事件是视图层到逻辑层的通讯方式。
事件可以将用户的行为反馈到逻辑层进行处理。
事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
事件对象可以携带额外信息,如id, dataset, touches。

(1)事件的使用方式

  • 在组件中绑定一个事件处理函数,如 bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。
    <view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>

  • 在相应的Page定义中写上相应的事件处理函数,参数是event。

    Page({

    tapName: function(event) {
      console.log(event)
    }
    

    })

事件分为冒泡事件(当一个组件上的事件被触发后,该事件会向父节点传递)和非冒泡事件(当一个组件上的事件被触发后,该事件不会向父节点传递),WXML的冒泡事件列表如下:
WXML冒泡事件列表

tips:除上表之外的其他组件自定义事件都是非冒泡事件,如<form/>的submit事件,<input/>的input事件,<scroll-view/>的scroll事件。

(2)事件的绑定

事件绑定的写法同组件的属性,以key、value的形式。 key以bindcatch开头,然后跟上事件的类型,如bindtap, catchtouchstart。 value是一个字符串,需要在对应的Page中定义同名的函数。不然当触发事件的时候会报错。

bind事件绑定不会阻止冒泡事件向上冒泡,catch事件绑定可以阻止冒泡事件向上冒泡。例如,如在下边这个例子中,点击inner view会先后触发handleTap3handleTap2(因为tap事件会冒泡到middle view,而middle view阻止了tap事件冒泡,不再向父节点传递),点击middle view会触发handleTap2,点击outter view会触发handleTap1

<view id="outter" bindtap="handleTap1">
  outer view
  <view id="middle" catchtap="handleTap2">
    middle view
    <view id="inner" bindtap="handleTap3">
      inner view
    </view>
  </view>
</view>

(3)事件对象

当组件触发事件时,逻辑层绑定该事件的处理函数会收到一个事件对象。事件对象属性如下:
事件对象属性

在组件中可以定义数据,这些数据将会通过事件传递给 SERVICE。书写方式:以data-开头,多个单词由连字符-链接,不能有大写(大写会自动转成小写)如data-element-type,最终在 event.target.dataset 中会将连字符转成驼峰elementType。

引用

WXML提供两种文件引用方式importinclude

(1)import

import可以在该文件中使用目标文件定义的template。 import有作用域的概念,即只会import目标文件中定义的template,而不会import目标文件import的template。

(2)include

include可以将目标文件除了<template/>的整个代码引入,相当于是拷贝到include位置。(感觉有点ejs中模板include的感觉)

WXS

WXS(WeiXin Script)是小程序的一套脚本语言,结合 WXML,可以构建出页面的结构。

注意:

wxs 不依赖于运行时的基础库版本,可以在所有版本的小程序中运行。
wxs 与 javascript 是不同的语言,有自己的语法,并不和 javascript 一致。
wxs 的运行环境和其他 javascript 代码是隔离的,wxs 中不能调用其他 javascript 文件中定义的函数,也不能调用小程序提供的API。
wxs 函数不能作为组件的事件回调。
由于运行环境的差异,在 iOS 设备上小程序内的 wxs 会比 javascript 代码快 2 ~ 20 倍。在 android 设备上二者运行效率无差异。

wxs用于页面渲染的使用示例,页面输出 hello world:

<!--wxml-->
<wxs module="m1">
var msg = "hello world";

module.exports.message = msg;
</wxs>

<view> {{m1.message}} </view>

wxs还可用于数据处理。

WXS模块

WXS 代码可以编写在 wxml 文件中的 <wxs> 标签内,或以 .wxs 为后缀名的文件内。

每一个 .wxs 文件和 <wxs> 标签都是一个单独的模块。
每个模块都有自己独立的作用域。即在一个模块里面定义的变量与函数,默认为私有的,对其他模块不可见。
一个模块要想对外暴露其内部的私有变量与函数,只能通过 module.exports 实现。

每个 wxs 模块均有一个内置的 module 对象,通过exports属性,可以对外共享本模块的私有变量与函数。

在.wxs模块中引用其他 wxs 文件模块,可以使用 require 函数。引用的时候,要注意如下几点:

只能引用 .wxs 文件模块,且必须使用相对路径。
wxs 模块均为单例,wxs 模块在第一次被引用时,会自动初始化为单例对象。多个页面,多个地方,多次引用,使用的都是同一个 wxs 模块对象。
如果一个 wxs 模块在定义之后,一直没有被引用,则该模块不会被解析与运行。

变量

WXS 中的变量均为值的引用。
没有声明的变量直接赋值使用,会被定义为全局变量。
如果只声明变量而不赋值,则默认值为 undefined。
var表现与javascript一致,会有变量提升。

注释

单行注释 // 多行注释/* */

数据类型

WXS 语言目前共有以下几种数据类型:

number : 数值
string :字符串
boolean:布尔值
object:对象
function:函数
array : 数组
date:日期
regexp:正则

(1)number 整数、小数

方法:

toString
toLocaleString
valueOf
toFixed
toExponential
toPrecision

(2)string

方法:

toString
valueOf
charAt
charCodeAt
concat
indexOf
lastIndexOf
localeCompare
match
replace
search
slice
split
substring
toLowerCase
toLocaleLowerCase
toUpperCase
toLocaleUpperCase
trim

(3)boolean

方法:

toString
valueOf

(4)object

方法:

toString:返回字符串 "[object Object]"

(5)function

方法:

toString:返回字符串 "[function Function]"。

(6)array

方法:

toString
concat
join
pop
push
reverse
shift
slice
sort
splice
unshift
indexOf
lastIndexOf
every
some
forEach
map
filter
reduce
reduceRight

(7)date

生成 date 对象需要使用 getDate()函数, 返回一个当前时间的对象。date类型还有很多方法

(8)regexp

生成 regexp 对象需要使用 getRegExp()函数。 方法有exectesttoString

tips: 数据类型的判断可以使用 constructor 属性。使用 typeof 也可以区分部分数据类型。

WXSS

WXSS(WeiXin Style Sheets)是一套样式语言,用于描述WXML的组件样式。WXSS具有CSS大部分特性。同时为了更适合开发微信小程序,对CSS进行了扩充以及修改。扩展的特性有尺寸单位、样式导入。

尺寸单位:px(responsive pixel),可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在iPhone6上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像。

样式导入:使用@import语句可以导入外联样式表,@import跟需要导入的外联样式表的相对路径(相对路径放在引号中),用;表示语句结束。

内联样式:框架组件上支持使用style、class属性来控制组件的样式。

  • style:静态的样式统一写到class中。style接收动态的样式,在运行时会进行解析,尽量避免将静态的样式写进style中,以免影响渲染速度。
    <view style="color:{{color}};" />

WXSS目前支持的选择器

兼容

小程序的功能不断的增加,但是旧版本的微信客户端并不支持新功能,所以在使用这些新能力的时候需要做兼容。文档会在组件,API等页面描述中带上各个功能所支持的版本号。

可以通过wx.getSystemInfo或者wx.getSystemInfoSync获取到小程序的基础库版本号。也可以通过 wx.canIUse 来判断是否可以在该基础库版本下直接使用对应的API或者组件。

接口

对于新增的 API,可以用以下代码来判断是否支持用户的手机。

if (wx.openBluetoothAdapter) {
  wx.openBluetoothAdapter()
} else {
  // 如果希望用户在最新版本的客户端上体验您的小程序,可以这样子提示
  wx.showModal({
    title: '提示',
    content: '当前微信版本过低,无法使用该功能,请升级到最新微信版本后重试。'
  })
}

参数

对于 API 的参数或者返回值有新增的参数,可以用以下代码判断。

wx.showModal({
  success: function(res) {
    if (wx.canIUse('showModal.cancel')) {
      console.log(res.cancel)
    }
  }
})

组件

对于组件,新增的属性在旧版本上不会被处理,不过也不会报错。如果特殊场景需要对旧版本做一些降级处理,可以这样子做。

Page({
  data: {
    canIUse: wx.canIUse('button.open-type.contact')
  }
})
<!-- wxml -->
<button wx:if="{{canIUse}}" open-type="contact"> 客服消息 </button>
<contact-button wx:else></contact-button>

运行机制

小程序没有重启的概念
当小程序进入后台,客户端会维持一段时间的运行状态,超过一定时间后(目前是5分钟)会被微信主动销毁
置顶的小程序不会被微信主动销毁
当收到系统内存告警也会进行小程序的销毁

再次打开逻辑: 基础库 1.4.0 开始支持,低版本需做兼容处理。

用户打开小程序的预期有以下两类场景:
A. 打开首页: 场景值有 1001, 1019, 1022, 1023, 1038, 1056
B. 打开小程序指定的某个页面: 场景值为除 A 以外的其他

再次打开逻辑

性能优化

setData是小程序开发中使用最频繁的接口,也是最容易引发性能问题的接口。

setData工作原理:

小程序的视图层目前使用 WebView 作为渲染载体,而逻辑层是由独立的 JavascriptCore 作为运行环境。在架构上,WebView 和 JavascriptCore 都是独立的模块,并不具备数据直接共享的通道。当前,视图层和逻辑层的数据传输,实际上通过两边提供的evaluateJavascript所实现。即用户传输的数据(由视图层去往逻辑层),需要将其转换为字符串形式传递,同时把转换后的数据内容拼接成一份 JS 脚本,再通过执行 JS 脚本的形式传递到两边独立环境。

而evaluateJavascript的执行会受很多方面的影响,数据到达视图层并不是实时的。同一进程内的 WebView 实际上会共享一个 JS VM,如果 WebView 内 JS 线程正在执行渲染或其他逻辑,会影响 evaluateJavascript 脚本的实际执行时间,另外多个 WebView 也会抢占 JS VM 的执行权限;另外还有 JS 本身的编译执行耗时,都是影响数据传输速度的因素。

常见的 setData 操作错误

(1)频繁的去 setData。 Android 下用户在滑动时会感觉到卡顿,操作反馈延迟严重;渲染有出现延时。

(2) 每次 setData 都传递大量新数据。

(3)后台态页面进行 setData。

图片资源

图片资源的主要性能问题在于大图片和长列表图片上,这两种情况都有可能导致 iOS 客户端内存占用上升,从而触发系统回收小程序页面。除了内存问题外,大图片也会造成页面切换的卡顿。

代码包大小的优化

小程序一开始时代码包限制为 1MB,后增加到 2MB 。代码包上限的增加对于开发者来说,能够实现更丰富的功能,但对于用户来说,也增加了下载流量和本地空间的占用。

控制代码包内图片资源: 小程序代码包经过编译后,会放在微信的 CDN 上供用户下载,CDN 开启了 GZIP 压缩,所以用户下载的是压缩后的 GZIP 包,其大小比代码包原体积会更小。 GZIP 对基于文本资源的压缩效果最好,在压缩较大文件时往往可高达 70%-80% 的压缩率,而如果对已经压缩的资源(例如大多数的图片格式)则效果甚微。

及时清理没有使用到的代码和资源: 在日常开发的时候,我们可能引入了一些新的库文件,而过了一段时间后,由于各种原因又不再使用这个库了,我们常常会只是去掉了代码里的引用,而忘记删掉这类库文件了。目前小程序打包是会将工程下所有文件都打入代码包内,也就是说,这些没有被实际使用到的库文件和资源也会被打入到代码包里,从而影响到整体代码包的大小。

组件

框架为开发者提供了一系列基础组件,开发者可以通过组合这些基础组件进行快速开发。

组件是视图层的基本组成单元。
组件自带一些功能与微信风格的样式。
一个组件通常包括开始标签和结束标签,属性用来修饰这个组件,内容在两个标签之内。

注意:所有组件与属性都是小写,以连字符-连接。

基础组件分为以下八大类:

视图容器view(视图容器)、 scroll-view(可滚动视图容器)、 swiper(可滑动视图容器)

基础内容icon(图标)、 text(文字)、 progress(进度条)

表单

button     按钮
form     表单
input     输入框
checkbox     多项选择器
radio     单项选择器
picker     列表选择器
picker-view     内嵌列表选择器
slider     滑动选择器
switch     开关选择器
label   标签

导航navigator(应用内跳转)

多媒体

audio     音频
image     图片
video     视频

地图map(地图)

画布canvas(画布)

客服会话contact-button(进入客服会话按钮)

API

框架提供丰富的微信原生API,可以方便的调起微信提供的能力,如获取用户信息,本地存储,支付功能等。

wx.on开头的API是监听某个事件发生的API接口,接受一个CALLBACK函数作为参数。当该事件触发时,会调用CALLBACK函数。
如未特殊约定,其他API接口都接受一个OBJECT作为参数。
OBJECT中可以指定success,fail,complete来接收接口调用结果。

网络API

wx.request      发起网络请求
wx.uploadFile      上传文件
wx.downloadFile      下载文件
wx.connectSocket    创建WebSocket连接
wx.onSocketOpen      监听WebSocket打开
wx.onSocketError    监听WebSocket错误
wx.sendSocketMessage    发送WebSocket消息
wx.onSocketMessage      接受WebSocket消息
wx.closeSocket      关闭WebSocket连接
wx.onSocketClose    监听WebSocket关闭

媒体API

wx.chooseImage    从相册选择图片,或者拍照
wx.previewImage    预览图片
wx.startRecord    开始录音
wx.stopRecord    结束录音
wx.playVoice    播放语音
wx.pauseVoice    暂停播放语音
wx.stopVoice    结束播放语音
wx.getBackgroundAudioPlayerState    获取音乐播放状态
wx.playBackgroundAudio    播放音乐
wx.pauseBackgroundAudio    暂停播放音乐
wx.seekBackgroundAudio    控制音乐播放进度
wx.stopBackgroundAudio    停止播放音乐
wx.onBackgroundAudioPlay    监听音乐开始播放
wx.onBackgroundAudioPause    监听音乐暂停
wx.onBackgroundAudioStop    监听音乐结束
wx.chooseVideo    从相册选择视频,或者拍摄

文件API

wx.saveFile    保存文件
wx.getSavedFileList    获取已保存的文件列表
wx.getSavedFileInfo    获取已保存的文件信息
wx.removeSavedFile    删除已保存的文件信息
wx.openDocument    打开文件

数据API

wx.getStorage    获取本地数据缓存
wx.getStorageSync    获取本地数据缓存
wx.setStorage    设置本地数据缓存
wx.setStorageSync    设置本地数据缓存
wx.getStorageInfo    获取本地缓存的相关信息
wx.getStorageInfoSync    获取本地缓存的相关信息
wx.removeStorage    删除本地缓存内容
wx.removeStorageSync    删除本地缓存内容
wx.clearStorage    清理本地数据缓存
wx.clearStorageSync    清理本地数据缓存

位置API

wx.getLocation    获取当前位置
wx.chooseLocation    打开地图选择位置
wx.openLocation    打开内置地图
wx.createMapContext    地图组件控制

设备API

wx.getNetworkType    获取网络类型
wx.onNetworkStatusChange    监听网络状态变化
wx.getSystemInfo    获取系统信息
wx.getSystemInfoSync    获取系统信息
wx.onAccelerometerChange    监听加速度数据
wx.startAccelerometer    开始监听加速度数据
wx.stopAccelerometer    停止监听加速度数据
wx.onCompassChange    监听罗盘数据
wx.startCompass    开始监听罗盘数据
wx.stopCompass    停止监听罗盘数据
wx.setClipboardData    设置剪贴板内容
wx.getClipboardData    获取剪贴板内容
wx.makePhoneCall    拨打电话
wx.scanCode    扫码

界面API

wx.showToast    显示提示框
wx.showLoading    显示加载提示框
wx.hideToast    隐藏提示框
wx.hideLoading    隐藏加载提示框
wx.showModal    显示模态弹窗
wx.showActionSheet    显示菜单列表
wx.setNavigationBarTitle    设置当前页面标题
wx.showNavigationBarLoading    显示导航条加载动画
wx.hideNavigationBarLoading    隐藏导航条加载动画
wx.navigateTo    新窗口打开页面
wx.redirectTo    原窗口打开页面
wx.switchTab    切换到 tabbar 页面
wx.navigateBack    退回上一个页面
wx.createAnimation    动画
wx.createCanvasContext    创建绘图上下文
wx.drawCanvas    绘图
wx.stopPullDownRefresh    停止下拉刷新动画

WXML节点信息API

wx.createSelectorQuery    创建查询请求
selectorQuery.select    根据选择器选择单个节点
selectorQuery.selectAll    根据选择器选择全部节点
selectorQuery.selectViewport    选择显示区域
nodesRef.boundingClientRect    获取布局位置和尺寸
nodesRef.scrollOffset    获取滚动位置
nodesRef.fields    获取任意字段
selectorQuery.exec    执行查询请求

开放接口

wx.login    登录
wx.getUserInfo    获取用户信息
wx.chooseAddress    获取用户收货地址
wx.requestPayment    发起微信支付
wx.addCard    添加卡券
wx.openCard    打开卡券
-------------本文结束感谢您的阅读-------------
坚持原创,您的支持将鼓励我继续创作!