微信小程序快速入门(持续更新中)

264 阅读18分钟

本文主要是对小程序的入门介绍以及常用功能的总结汇总,因为官方文档毕竟比较庞杂,需要花很多时间去学习,如果你想快速入门,希望本文可以给你一些帮助,当然深入的学习还是要去官网哦。

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单位进行屏幕适配。

复古风格
图片来自:juejin.im/post/684490…

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 事件绑定
  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必须是是一个字符传,指定事件处理函数的名字.如果名字是空字符串代表禁用此事件。

事件分为冒泡和非冒泡事件,详情

  1. catch: 除 bind 外,也可以用 catch 来绑定事件。与 bind 不同, catch 会阻止事件向上冒泡。
  2. 互斥事件绑定:mut-bind。自基础库版本 [2.8.2]起,除 bind 和 catch 外,还可以使用 mut-bind 来绑定事件。一个 mut-bind 触发后,如果事件冒泡到其他节点上,其他节点上的 mut-bind 绑定函数不会被触发,但 bind 绑定函数和 catch 绑定函数依旧会被触发。
  3. 自基础库版本 [1.5.0] 起,触摸类事件支持捕获阶段事件绑定,详情
  4. 事件对象的属性也在第四条的详情中进行查看
4.4.2 简易双向绑定
// 在value前面加上`model:` 即可完成简易双向绑定,也就是说当用户修改input里的值时,this.data.value也会跟着发生改变
<input model:value="{{value}}" />

5、API

5.1 通常小程序API分为以下几种类型

  1. 事件监听 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总结

  1. wx.env 环境变量,文件路径。
  2. boolean wx.canIUse(string schema) 判断小程序的API,回调,参数,组件等是否在当前版本可用。
  3. wx.updateWeChatApp(Object object) 当微信客户端版本过低时跳转到更新客户端页面(只是跳转并没有强制更新)。
  4. UpdateManager wx.getUpdateManager()获取全局唯一的版本更新管理器,用于管理小程序更新。

应用及事件api
此类事件几乎都和App.js内的生命周期对应。

  1. wx.onPageNotFound(function listener):监听页面不存在事件。

页面跳转api

  1. wx.switchTab : 跳转到tabBar页面,并关闭其他所有非tabBar页面.
  2. wx.reLaunch(Object object) 关闭所有页面,打开到应用内的某个页面.
  3. wx.redirectTo(obj) 关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。
  4. wx.navigateTo(Object object) 保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面(小程序中页面栈最多十层)。可通过events属性和EventChannel对象进行跳转前后页面间数据通信。

交互api

  1. wx.showLoading(obj) 显示loading提示框,需使用wx.hideLoading()关闭。
  2. wx.showActionSheet(Object object) 显示操作菜单,自定义更多操作。
  3. wx.enableAlertBeforeUnload(Object object) 开启返回询问对话框,手势滑动返回不拦截。

网络相关api

  1. wx.request()
  2. wx.downloadFile() 下载文件到本地
  3. wx.uploadFile() 将本地文件上传到服务器

缓存API

  1. wx.setStorageSync(string key, any data) 永久缓存,单个值上限为1M,同一个微信用户,同一个小程序 storage 上限为 10MB。注意不要使用stoage作为运行时的全局状态管理,而是用他来存储固定的数据。对应移除操作:wx.removeStorageSync(string key)。还可批量更新、批量获取,全部获取...,详情请看相关api。
  • 缓存隔离策略: 在一般的移动端开发过程中,我们在本地存储数据时最好跟登录信息绑定,避免出现退出登录后信息仍在使用的问题。但在微信小程序中,storage 以用户维度隔离,同一台设备上,A 用户无法读取到 B 用户的数据;不同小程序之间也无法互相读写数据。避免了之前可能存在的数据混乱的问题。
  1. wx.login() 小程序登录流程入口。

其他api

  1. wx.setNavigationBarTitle(Object object) 动态设置导航条。
  2. wx.loadFontFace(Object object) 动态加载网络字体。

6、小程序组件

组件公共规则

  • 所有组件与属性都是小写,以连字符-连接
  • 所有组件都有以下几个属性:
    • id、class、style、hidden(布尔值)、data-*、bind*/catch*

6.1 常用组件

视图组件

  1. view 视图容器。
  2. movable-view 可移动的视图容器,在页面中可以拖拽滑动,必须被包裹在movable-area组件中,movable-area组件用于设置可移动的区域范围,需要设置宽高。
  3. page-container 假页容器,效果类似于popup,在用户点击返回的时候关闭当前假页面(popup没法控制返回按钮),一般用于半屏页面。
  4. scroll-view 可滚动视图区域。
  5. swiper 滑动组件(走马灯),与swiper-item一起使用。
  6. icon 图标组件。
  7. progress 进度条。
  8. text 文本。
  9. button 按钮。

表单组件

  1. form 表单,可在button按钮上绑定form-type属性用来提交表单。
    • 内置 behaviors如wx://form-field,可用来将自定义组件和表单关联起来,从而在提交表单时获取到自定义组件的值。
  2. input 输入框。
  3. picker 从底部弹起的滚动选择器。
  4. picker-view 嵌入页面的滚动选择器。
  5. radio 单项选择器。

其他组件

  1. navigator 页面链接,支持设置type来对应不同的跳转方式,也支持跳转到其他小程序。
  2. camera 相机或扫码,mode对应normal和scanCode,需要结合js使用。

        const ctx = wx.createCameraContext();
        ctx.takePhoto({ // 调起页面中的camera组件
              quality: 'high',
              success: (res) => {
                this.setData({
                  src: res.tempImagePath
                })
              }
            })
  1. image 图片,支持 JPG、PNG、SVG、WEBP、GIF 等格式。
  2. audio 音频播放器。
  3. video 视频播放器。

6.2 自定义组件

  1. 新建组件,元素与页面类似。在组件的json文件里配置,"component": true
  2. 在组件wxss中不应使用ID选择器、属性选择器和标签名选择器。
  3. 组件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 定义段时建议重新测试一下。
  1. 插槽slot: 在组件模板中可以提供一个 <slot> 节点,用于承载组件引用时提供的子节点.
    • 还可以启用多slot,通过name来区分,详情
  2. 组件样式:
    • 除继承样式(如font、color)外, app.wxss 中的样式、组件所在页面的的样式对自定义组件无效(除非更改组件样式隔离选项)。
    • 可以给组件传递externalClasses选项,来指定接收的外部样式。
    • 在自定义组件中,尽量使用class选择器定义组件样式。
    • 组件样式隔离规则比较复杂,可以直接看官网
  3. 自定义组件扩展definitionFilter:
    需要和behavior结合起来使用,本质就是使用behavior在组件外部控制组件数据。

6.3 组件间通信

  1. 在wxml中指定属性值(父传子)
  2. 事件通信(子传父:类似于react中的回调函数)

    父组件内:
    <child bindmyevent="onMyEvent" />
    子组件内触发事件通信:
    this.triggerEvent("myevent", detail, option);
  1. 父组件还可以通过 this.selectComponent 方法获取子组件实例对象,这样就可以获取子组件实例上的任意数据。
  2. 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() {
      // 页面被隐藏
    },
  }

})
  • 常用的生命周期方法
  1. created:刚刚创建好组件实例(类似于react中的constructor),适合给this添加属性,不适合setData。
  2. attached:组件初始化完毕,适合做一些初始化数据的工作比如发请求。
  3. detached:组件离开页面节点树时,也就是卸载时触发。

7、小程序开发流程介绍

1、注册app:在app.js文件中初始化App实例,并做相应配置,开发者可以通过getApp()获取程序实例及实例上的数据。
2、注册页面:在app.json中配置页面路径,然后去page.js中初始化page实例。有些复杂页面中Page构造器可能并不好用,可以使用Component构造器去构造页面实例。
3、配置网络域名及注意事项:详情
未完待续...

8、开发第三方自定义组件(npm包)

8.1 在小程序中使用npm
  1. 像在其他项目中安装npm包一样,小程序也是在package.json所在的目录下进行npm install,去安装npm包。不同的是,小程序的package.json文件不一定在根目录下。

此处要求参与构建 npm 的 package.json 需要在 project.config.json 定义的 miniprogramRoot 之内。后面的版本有所调整,具体看详情。

  1. 在开发者工具中进行构建:工具 --> 构建 npm

9、分包

10、router页面路由器对象

  • 获取router对象:this.pageRouter、this.router(在自定义组件中相对于组件的路径)
  • 与wx对象的switchTabreLaunchredirectTonavigateTonavigateBack 功能相同,router对象也有这些跳转方法,不同的是router的相对路径永远是相对于this指代的页面或组件,具有更好的基路径稳定性,因此也更为常用。