本文主要是对小程序的入门介绍以及常用功能的总结汇总,因为官方文档毕竟比较庞杂,需要花很多时间去学习,如果你想快速入门,希望本文可以给你一些帮助,当然深入的学习还是要去官网哦。
1、小程序简介
微信小程序提供了一个简单、高效的应用开发框架和丰富的组件及API,帮助开发者在微信中开发具有原生 APP 体验的服务。
1.1 小程序的优势
(1)用户量大,推广成本低
(2)开发适配成本低,微信会帮助我们进行移动端的适配,开发人员只需关注安卓、ios客户端之间的差异
(3)高效和简单的开发,规模小,易试错
(4)跨平台
(5)无需安装,加载更快(其实也是需要安装的,因为体积非常的小,所以表面看起来不需要安装;规定体积不超过2M,发布前需要微信官方审核)
1.2 小程序的劣势
(1)小程序的逻辑层和渲染层是分开的,逻辑层运行在 JSCore 中,并没有一个完整浏览器对象,因而缺少相关的DOM API和BOM API。
(2)同时 JSCore 的环境同 NodeJS 环境也是不尽相同,所以一些 NPM 的包在小程序中也是无法运行的。
ps:网页需要面对不同的浏览器去进行适配,但小程序需要面对的不是不同的浏览器,而是三大不同的运行环境(微信客户端运行环境)。
2、开发前准备工作
(1)注册,每个小程序都需要注册一个唯一的AppID(如果你只是想练习不想发版也可以先不注册,直接使用测试id即可)。
(2)下载小程序开发工具
(3)查看小程序开发者工具介绍
2.1 微信小程序官方文档阅读,好多文档怎么看?
- 指南:必看,是对微信小程序各个功能的大致介绍,并配有详细文档地址
- 框架:小程序框架相关信息,如全局配置、页面配置、wxml语法等
- 组件:微信原生提供的各种小程序组件介绍
- API:微信提供的各种能力介绍,如获取用户信息、微信扫一扫、微信支付等
- 其他文档:用到再看
3、 小程序语言介绍
微信小程序提供了自己的视图层描述语言WXML、WXSS(相当于html和css),结合javascript来开发;小程序没有DOM和BOM,基于组件化开发,支持模块化。在小程序中特别推荐使用flex布局,并且提供了rpx单位进行屏幕适配。
3.1 目录结构介绍
- pages: 包含小程序的所有页面,每个页面就是一个文件夹里面包含下面四个文件,且无需在wxml中手动引入wxss、js、json文件。
- wxml文件:类似于html,用于书写页面结构
- wxss文件:样式文件,类似于css
- json文件:保存页面的配置信息,详情(功能很强大)
- js文件
- app.json: 全局配置文件,包括了小程序的所有页面路径、界面表现、网络超时时间、底部 tab 等。
- project.config.json:微信开发者工具配置,包括界面的主体颜色、代码自动压缩等。
- sitemap.json:用来配置小程序及其页面是否允许被微信索引。
tips:在小程序中不是所有的文件类型都支持上传的,只有在白名单里的文件类型才会被上传
3.1.1 WXML:
wxml和html类似,都是由标签和属性构成的,不同的是wxml的标签名和html标签名有所区别,并且wxml既包含了一些基础的元素标签(例如view、text、button),又提供了许多包装了很多能力的标签,例如地图、视频、音频等标签。常用组件在下方6.1章节进行介绍,这里先不过多赘述。先来了解一下wxml具有的能力:
1、数据绑定 {{name}} ,通过双括号引用js文件中的数据
2、条件渲染:
<view wx:if="{{length > 5}}"> 1 </view>
<view wx:elif="{{length > 2}}"> 2 </view>
<view wx:else> 3 </view>
3、列表渲染:
<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="it" wx:key="id">
{{idx}}: {{it.message}} // 如果不指定,默认就是index、item
</view>
// wx:key 用于指定列表渲染时每一项的key值,提高渲染效率并在数组改变时保留某些项的状态
// 可以是某个属性的名字或者‘*this’,表示item自身
4、文件引入:
- import: <import src="item.wxml"/> // 相当于引入了item.wxml的作用域,可以在本页面中随意使用item.wxml中的template
- include:include 可以将目标文件中除了 <template/> <wxs/> 外的整个代码引入,相当于是拷贝到 include 位置。
5、模板:模板类似于我们常说的组件,但是没有js逻辑,只是单纯的展示组件
/* 定义模版 template.wxml */
<template name="myItem">
<view>
<text> {{age}} </text>
<text> 1 </text>
</view>
</template>
/* 引用模板*/
<import src="/pages/template.wxml" /> /* 首先引入模板文件,如果该模板有样式文件,则需要在当前页面的样式文件里引入该模板的样式文件*/
<template is="myItem" data="{{age: 18}}"/>
3.1.2 WXSS
新增特性:
- 小程序样式适配方案:通过rpx设置大小,以适应不同的屏幕,完整显示相同的内容尺寸,rpx可以根据屏幕宽度自适应,规定屏幕的宽度为750rpx。
- 样式导入: @import "相对路径"
- 仅支持部分选择器,例如class选择器,详情
- 微信官方提供了基础样式库:WeUI.wxss
- 内联样式
// 一般用于动态样式,例如这里color值是从js文件中动态获取的
<view style="color:{{color}};" />
3.1.3 js脚本
- 自带模块化功能:不同文件定义的变量,作用域都只在当前的脚本文件中
3.2 微信小程序运行机制
- 微信客户端打开小程序,下载小程序包到本地
- 通过app.json的pages字段,获取第一个配置页面进行渲染
- 小程序启动之后,在
app.js定义的App实例的onLaunch回调会被执行
3.2.1 小程序的初始渲染缓存
小程序页面的初始化分为两个部分。
- 逻辑层初始化:载入必需的小程序代码、初始化页面 this 对象(也包括它涉及到的所有自定义组件的 this 对象)、将相关数据发送给视图层。
- 视图层初始化:载入必需的小程序代码,然后等待逻辑层初始化完毕并接收逻辑层发送的数据,最后渲染页面。
如上所述,只有逻辑层执行完毕将数据发送给视图层后,页面才能渲染出来,这势必会影响到用户的体验,所以我们可以启用初始渲染缓存机制,在第一次打开页面时缓存页面的数据,在第二次打开页面时先用缓存的数据进行页面的渲染,随后等逻辑层执行完毕再使用最新的数据进行页面的渲染。 利用初始渲染缓存,可以:
- 快速展示出页面中永远不会变的部分,如导航栏;
- 预先展示一个骨架页,提升用户体验;
- 展示自定义的加载提示;
- 提前展示广告,等等。
如何使用:
- 若想启用初始渲染缓存,最简单的方法是在页面的
json文件中添加配置项"initialRenderingCache": "static" - 如果想要对所有页面启用,可以在
app.json的window配置段中添加这个配置
注意:这种情况下,初始渲染缓存记录的是页面 data 应用在页面 WXML 上的结果,不包含任何 setData 的结果。也就是直接写在data上的数据,而不是后续setData的数据,也就是静态数据。 - 动态初始化渲染配置:
"initialRenderingCache": "dynamic",比较耗费性能,详情
3.2.2 js运行差异
由于逻辑层内核的不同,不同微信客户端对js的支持情况有所差异,详情请看官方文档,这里需要特别注意的是对promise的支持情况,在iOS 环境下的 Promise 是一个使用 setTimeout 模拟的 Polyfill,所以也就没有微任务的特性。
3.2.3 小程序运行时的相关概念
小程序的启动可以分为冷启动和热启动:
- 冷启动:第一次启动或销毁后重新启动。(关闭小程序30分钟后才会被销毁)
- 热启动:未被销毁,只是被切到后台时再次启动。(显示到界面上则为前台,反之为后台)
- 挂起:被切换到后台后5s,处于挂起状态,js线程停止工作,但音乐、位置信息等可以正常运行。
- 销毁:一般是挂起30分钟后销毁,也有可能因系统性能等原因被销毁,基础库 1.1.0 及以上,1.4.0 以下版本: 当用户从扫一扫、转发等入口(场景值为1007, 1008, 1011, 1025)进入小程序,且没有置顶小程序的情况下退出,小程序会被销毁。
3.2.4 小程序的更新机制
小程序的更新分为同步更新和异步更新,我们也可手动进行更新 wx.getUpdateManager。我们还可以在管理后台设置优先使用的本地版本和最低可用版本。
3.3 组件 & API
微信小程序为开发者提供了很多现成的能力,例如封装好的很多组件,如:map、各种视图容器、表单组件等;还有各种API,如:获取用户信息、微信扫一扫、微信支付等。
4、小程序框架
微信小程序的框架分为视图层和逻辑层,视图层有多个渲染线程(多个页面对应多个线程)进行工作,逻辑层就是一个js线程进行逻辑处理工作,他们之间通过微信客户端进行数据交互。框架的核心是一个响应的数据绑定系统,可以让视图和逻辑保持一致。
4.1 生命周期
与react和vue类似,小程序也有生命周期的概念,不同的是小程序不仅有组件的生命周期还有app实例的生命周期。 App生命周期文档 page生命周期文档
4.2 页面路由
在小程序中所有页面的路由全部由框架进行管理,小程序框架维护了一套页面栈(路由信息栈),开发者可以使用getCurrentPages()获取页面栈信息。不同的路由方式(例如打开新页面、重定向等)会触发页面不同的生命周期函数,详情见文档。
路由api详情请看下方api章节
4.3 模块化
- 支持使用exports、module.exports导出模块内容
- 使用require导入其他模块内容,同包不同包都可以。支持异步链式调用。
4.4 事件系统
与网页类似,小程序也有自己的事件系统,例如点击事件:tap
4.4.1 事件绑定
- bind
<view id="tapTest" data-hi="Weixin" bindtap="handleTap"> Click me! </view>
// 使用‘bind+事件名’(或者‘bind:事件名’)作为绑定事件处理函数的属性,其中handleTap是事件处理函数的名字
// 事件处理函数的名字也可以使用数据进行动态绑定,如:
<view id="tapTest" data-hi="Weixin" bindtap="{{handleName}}"> Click me! </view>
// 此时this.data.handleName必须是是一个字符传,指定事件处理函数的名字.如果名字是空字符串代表禁用此事件。
事件分为冒泡和非冒泡事件,详情
- catch: 除
bind外,也可以用catch来绑定事件。与bind不同,catch会阻止事件向上冒泡。 - 互斥事件绑定:mut-bind。自基础库版本 [2.8.2]起,除
bind和catch外,还可以使用mut-bind来绑定事件。一个mut-bind触发后,如果事件冒泡到其他节点上,其他节点上的mut-bind绑定函数不会被触发,但bind绑定函数和catch绑定函数依旧会被触发。 - 自基础库版本 [1.5.0] 起,触摸类事件支持捕获阶段事件绑定,详情
- 事件对象的属性也在第四条的详情中进行查看
4.4.2 简易双向绑定
// 在value前面加上`model:` 即可完成简易双向绑定,也就是说当用户修改input里的值时,this.data.value也会跟着发生改变
<input model:value="{{value}}" />
5、API
5.1 通常小程序API分为以下几种类型
- 事件监听 API
// 以on关键字开头
wx.onCompassChange(function (res) { // res为事件的相关数据
console.log(res.direction)
})
2. 同步API
以 Sync 结尾的 API 都是同步 API
try {
const res = wx.setStorageSync('key', 'value')
} catch (e) {
console.error(e)
}
3. 异步API
// 支持promise,具体看文档
wx.login({
success(res) {
console.log(res.code)
}
})
4. 云开发API
5.2 获取节点信息API(暂时用不到还没总结)
类似于dom操作,可以获取节点在页面上的位置等信息
5.3 常用api总结
- wx.env 环境变量,文件路径。
- boolean wx.canIUse(string schema) 判断小程序的API,回调,参数,组件等是否在当前版本可用。
- wx.updateWeChatApp(Object object) 当微信客户端版本过低时跳转到更新客户端页面(只是跳转并没有强制更新)。
- UpdateManager wx.getUpdateManager()获取全局唯一的版本更新管理器,用于管理小程序更新。
应用及事件api
此类事件几乎都和App.js内的生命周期对应。
- wx.onPageNotFound(function listener):监听页面不存在事件。
页面跳转api
- wx.switchTab : 跳转到tabBar页面,并关闭其他所有非tabBar页面.
- wx.reLaunch(Object object) 关闭所有页面,打开到应用内的某个页面.
- wx.redirectTo(obj) 关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
- wx.navigateTo(Object object) 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面(小程序中页面栈最多十层)。可通过events属性和EventChannel对象进行跳转前后页面间数据通信。
交互api
- wx.showLoading(obj) 显示loading提示框,需使用wx.hideLoading()关闭。
- wx.showActionSheet(Object object) 显示操作菜单,自定义更多操作。
- wx.enableAlertBeforeUnload(Object object) 开启返回询问对话框,手势滑动返回不拦截。
网络相关api
- wx.request()
- wx.downloadFile() 下载文件到本地
- wx.uploadFile() 将本地文件上传到服务器
缓存API
- wx.setStorageSync(string key, any data) 永久缓存,单个值上限为1M,同一个微信用户,同一个小程序 storage 上限为 10MB。注意不要使用stoage作为运行时的全局状态管理,而是用他来存储固定的数据。对应移除操作:wx.removeStorageSync(string key)。还可批量更新、批量获取,全部获取...,详情请看相关api。
- 缓存隔离策略: 在一般的移动端开发过程中,我们在本地存储数据时最好跟登录信息绑定,避免出现退出登录后信息仍在使用的问题。但在微信小程序中,storage 以用户维度隔离,同一台设备上,A 用户无法读取到 B 用户的数据;不同小程序之间也无法互相读写数据。避免了之前可能存在的数据混乱的问题。
- wx.login() 小程序登录流程入口。
其他api
- wx.setNavigationBarTitle(Object object) 动态设置导航条。
- wx.loadFontFace(Object object) 动态加载网络字体。
6、小程序组件
组件公共规则:
- 所有组件与属性都是小写,以连字符
-连接 - 所有组件都有以下几个属性:
- id、class、style、hidden(布尔值)、data-*、bind*/catch*
6.1 常用组件
视图组件
- view 视图容器。
- movable-view 可移动的视图容器,在页面中可以拖拽滑动,必须被包裹在movable-area组件中,movable-area组件用于设置可移动的区域范围,需要设置宽高。
- page-container 假页容器,效果类似于popup,在用户点击返回的时候关闭当前假页面(popup没法控制返回按钮),一般用于半屏页面。
- scroll-view 可滚动视图区域。
- swiper 滑动组件(走马灯),与swiper-item一起使用。
- icon 图标组件。
- progress 进度条。
- text 文本。
- button 按钮。
表单组件
- form 表单,可在button按钮上绑定form-type属性用来提交表单。
- 内置 behaviors如wx://form-field,可用来将自定义组件和表单关联起来,从而在提交表单时获取到自定义组件的值。
- input 输入框。
- picker 从底部弹起的滚动选择器。
- picker-view 嵌入页面的滚动选择器。
- radio 单项选择器。
其他组件
- navigator 页面链接,支持设置type来对应不同的跳转方式,也支持跳转到其他小程序。
- camera 相机或扫码,mode对应normal和scanCode,需要结合js使用。
const ctx = wx.createCameraContext();
ctx.takePhoto({ // 调起页面中的camera组件
quality: 'high',
success: (res) => {
this.setData({
src: res.tempImagePath
})
}
})
- image 图片,支持 JPG、PNG、SVG、WEBP、GIF 等格式。
- audio 音频播放器。
- video 视频播放器。
6.2 自定义组件
- 新建组件,元素与页面类似。在组件的json文件里配置,"component": true
- 在组件wxss中不应使用ID选择器、属性选择器和标签名选择器。
- 组件js文件配置Component构造器,具体用法请看详情
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String, // 定义属性的类型和默认值
value: 'default value',
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod: function(){}
}
})
页面使用自定义组件时需要配置json文件,引入该组件
{
"usingComponents": {
"component-tag-name": "path/to/the/custom/component"
}
}
// 开发者工具 1.02.1810190 及以上版本支持在 app.json 中声明 usingComponents 字段,在此处声明的自定义组件视为全局自定义组件,在小程序内的页面或自定义组件中可以直接使用而无需再声明。
一些需要注意的细节:
- 因为 WXML 节点标签名只能是小写字母、中划线和下划线的组合,所以自定义组件的标签名也只能包含这些字符。
- 自定义组件和页面所在项目根目录名不能以“wx-”为前缀,否则会报错。
- 注意,是否在页面文件中使用 usingComponents 会使得页面的 this 对象的原型稍有差异,包括:
- 使用 usingComponents 页面的原型与不使用时不一致,即 Object.getPrototypeOf(this) 结果不同。
- 使用 usingComponents 时会多一些方法,如 selectComponent 。
- 出于性能考虑,使用 usingComponents 时, setData 内容不会被直接深复制,即 this.setData({ field: obj }) 后 this.data.field === obj 。(深复制会在这个值被组件间传递时发生。)如果页面比较复杂,新增或删除 usingComponents 定义段时建议重新测试一下。
- 插槽slot: 在组件模板中可以提供一个
<slot>节点,用于承载组件引用时提供的子节点.- 还可以启用多slot,通过name来区分,详情
- 组件样式:
- 除继承样式(如font、color)外,
app.wxss中的样式、组件所在页面的的样式对自定义组件无效(除非更改组件样式隔离选项)。 - 可以给组件传递externalClasses选项,来指定接收的外部样式。
- 在自定义组件中,尽量使用class选择器定义组件样式。
- 组件样式隔离规则比较复杂,可以直接看官网
- 除继承样式(如font、color)外,
- 自定义组件扩展definitionFilter:
需要和behavior结合起来使用,本质就是使用behavior在组件外部控制组件数据。
6.3 组件间通信
- 在wxml中指定属性值(父传子)
- 事件通信(子传父:类似于react中的回调函数)
父组件内:
<child bindmyevent="onMyEvent" />
子组件内触发事件通信:
this.triggerEvent("myevent", detail, option);
- 父组件还可以通过
this.selectComponent方法获取子组件实例对象,这样就可以获取子组件实例上的任意数据。 - behaviors: 每个
behavior可以包含一组属性、数据、生命周期函数和方法。组件引用它时,它的属性、数据和方法会被合并到组件中,生命周期函数也会在对应时机被调用(基础库2.9.2开始支持),例如定义一个behavior,在页面中引入它,就可以在相应的生命周期执行这些公用的代码段。同名属性和方法覆盖规则看详情。微信小程序还内置了一些behaviors,可以自己去官网看看。
// 定义behavior
module.exports = Behavior({ // behavior等生命周期优先于组件的生命周期,先执行
attached: function() {
// 页面创建时执行
console.info('Page loaded!')
},
detached: function() {
// 页面销毁时执行
console.info('Page unloaded!')
}
})
// 引入behavior
var myBehavior = require('my-behavior')
Component({
behaviors: [myBehavior],
})
5. 数据监听器
用来监听属性或数据字段的变化,详情官网写的比较简洁详细就不再赘述了。
6.4 组件的生命周期
如何定义生命周期方法:
// 有两种方式去定义(1、2)
Component({
lifetimes: { // 1、写在这里面优先级更高
attached: function() {
// 在组件实例进入页面节点树时执行
}
},
// 2、以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容,优先级低
attached: function() {
...
},
pageLifetimes: { // 组件也可以引用所在页面的生命周期,但只限于show、hide、resize和routeDone。
show: function() {
// 页面被展示
},
hide: function() {
// 页面被隐藏
},
}
})
常用的生命周期方法
- created:刚刚创建好组件实例(类似于react中的constructor),适合给this添加属性,不适合setData。
- attached:组件初始化完毕,适合做一些初始化数据的工作比如发请求。
- detached:组件离开页面节点树时,也就是卸载时触发。
7、小程序开发流程介绍
1、注册app:在app.js文件中初始化App实例,并做相应配置,开发者可以通过getApp()获取程序实例及实例上的数据。
2、注册页面:在app.json中配置页面路径,然后去page.js中初始化page实例。有些复杂页面中Page构造器可能并不好用,可以使用Component构造器去构造页面实例。
3、配置网络域名及注意事项:详情
未完待续...
8、开发第三方自定义组件(npm包)
8.1 在小程序中使用npm:
- 像在其他项目中安装npm包一样,小程序也是在package.json所在的目录下进行npm install,去安装npm包。不同的是,小程序的package.json文件不一定在根目录下。
此处要求参与构建 npm 的 package.json 需要在 project.config.json 定义的 miniprogramRoot 之内。后面的版本有所调整,具体看详情。
- 在开发者工具中进行构建:工具 --> 构建 npm
9、分包
10、router页面路由器对象
- 获取router对象:this.pageRouter、this.router(在自定义组件中相对于组件的路径)
- 与wx对象的
switchTab、reLaunch、redirectTo、navigateTo、navigateBack功能相同,router对象也有这些跳转方法,不同的是router的相对路径永远是相对于this指代的页面或组件,具有更好的基路径稳定性,因此也更为常用。