小程序开发入门

DanJesse 发布于1年前
0 条问题

在体验小程序开发之后,我上线了一个小应用 527菜谱 ,同时也发现了小程序开发中有各种注意要点,不然一定会踩坑,小程序开发官方文档里已经有很详细说明,这里我对文档中一些要点做以下总结,方便记忆查询

小程序特点

  • 多个页面可共享JS运行环境
  • JS运行与页面渲染分离,提升页面的渲染性能
  • 提供了native的能力(扫码、离线、地图等)
  • 接近原生的用户体验
  • 自带ES6支持
  • wxss可使用 rpx 单位适配不同屏幕
  • 退出小程序后不会立即销毁,会在后台继续跑5分钟,在这期间用户切回小程序时速度快

注册与开发流程

注册流程

  • 申请账号

    账号信息 - 邮箱激活 - 信息登记

    小程序开发入门
  • 设置

    • 关联公众号
    • 绑定微信开放平台账号
    • 获取 appid 与 appSecret
    • 配置服务器域名(最多配置10个,每月最多修改5次)
    • 消息推送
    • 腾讯云
      小程序开发入门

    个人小程序不支持 微信支付、扫普通链接二维码打开小程序、打开网页

开发流程

  • 使用开发者工具新建项目
  • 上传项目发布为 开发版
  • 提交预览版为 审核版
  • 发布审核版为 正式版

开发者工具简介

小程序开发入门

  • 新建页面:右键新建Page / app.json 中添加页面
  • 自动保存
  • 实时预览
  • 代码自动补全
  • git状态显示
  • 支持特殊场景调试:扫码、微信支付、使用自定参数、进入场景值、转发、中转小程序
  • 小程序开发助手
  • 第三方平台
  • 云测试(直机测试)
  • 运行环境与ES支持情况

原理与框架说明

基本原理

基本框架

  • 基于webview
  • 通过 WeixinJSBridge 实现视图层和逻辑层的通信
  • 每个视图都是独立的Webview
  • 逻辑和UI运行在2个独立的Webview中
    小程序开发入门

通信原理

  • 开发者工具中是基于 window.postMessage
  • IOS中基于 window.webkit.messageHandlers.invokeHandler.postMessage
  • Android中基于 WeixinJSCore.invokeHandler
// 发送消息
window.postMessage({ postdata }, "*");
// 接收消息
window.addEventListener("message", receiveMessage, false);

postMessage MDN

工程目录结构

  • wxml 描述界面
  • wxss 描述样式
  • js 处理逻辑
  • json 页面配置
project
├── pages
| ├── index
| | ├── index.json index 页面配置
| | ├── index.js index 页面逻辑
| | ├── index.wxml index 页面结构
| | └── index.wxss index 页面样式表
| └── log
| ├── log.json log 页面配置
| ├── log.wxml log 页面逻辑
| ├── log.js log 页面结构
| └── log.wxss log 页面样式表
├── app.js 小程序逻辑
├── app.json 小程序公共设置
└── app.wxss 小程序公共样式表

对于每个页面下相关配置的四个文件必须具有相同的路径与文件名

应用配置

app.json

// app.json
{
 // 定义小程序中有哪些页面
 "pages":[
 "pages/index/index",
 "pages/logs/logs"
 ],
 
 // 窗口的样式
 "window":{
 "backgroundTextStyle":"light",
 "navigationBarBackgroundColor": "#fff",
 "navigationBarTitleText": "Demo",
 "navigationBarTextStyle":"black",
 "enablePullDownRefresh": true
 },
 
 // 底部tab的内容和样式
 "tabBar": {
 // tab的具体内容
 "list": [
 {
 "pagePath": "pages/index/index",
 "text": "首页"
 }, 
 {
 "pagePath": "pages/logs/logs",
 "text": "日志"
 }
 ]
 },
 
 // 设置不同请求的网络超时
 "networkTimeout": {
 "request": 10000,
 "downloadFile": 10000
 },
 
 // 是否开启debug模式,开启debug模式之后可以在微信开发者工具的控制台中看到整个APP,以及每个页面的生命周期日志
 "debug": true
}

应用注册

App({
 // 监听小程序初始化
 onLaunch: function(options){
 // Do something initial when launch.
 // 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
 },
 // 监听小程序显示
 onShow: function(options){
 // Do something when show.
 // 当小程序启动,或从后台进入前台显示,会触发 onShow
 },
 // 监听小程序隐藏
 onHide: function(){
 // Do something when hide.
 // 当小程序从前台进入后台,会触发 onHide
 },
 // 错误监听函数
 onError: function(msg){
 console.log(msg)
 // 当小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息
 },
 globalData: 'I am global data'
})

页面生命周期

//index.js
Page({
 // 页面状态数据
 data: {
 text: "This is page data."
 },
 // 页面加载
 onLoad: function(options){
 // Do some initialize when page load.
 // 一个页面只会调用一次,可以在 onLoad 中获取打开当前页面所调用的 query 参数
 },
 // 页面初次渲染完成
 onReady: function(){
 // Do something when page ready.
 // 一个页面只会调用一次,代表页面已经准备妥当,可以和视图层进行交
 },
 // 页面显示
 onShow: function(){
 // Do something when page show.
 // 每次打开页面都会调用一次
 },
 // 页面隐藏
 onHide: function(){
 // Do something when page hide.
 // 当 navigateTo 或底部 tab 切换时调用
 },
 // 页面卸载
 onUnload: function(){
 // Do something when page close.
 // 当 redirectTo 或 navigateBack 的时候调用
 },
 // 监听 下拉刷新 事件
 onPullDownRefresh: function(){
 // Do something when pull down.
 // 监听用户下拉刷新事件。
 // 需要在 app.json 的 window 选项中或页面配置中开启enablePullDownRefresh。
 // 当处理完数据刷新后,wx.stopPullDownRefresh 可以停止当前页面的下拉刷新。
 },
 // 监听 上拉触底 事件
 onReachBottom: function(){
 // Do something when page reach bottom.
 // 监听用户上拉触底事件。
 // 可以在 app.json 的 window 选项中或页面配置中设置触发距离onReachBottomDistance。
 // 在触发距离内滑动期间,本事件只会被触发一次
 },
 // 监听 用户转发 事件
 onShareAppMessage: function (){
 // return custom share data when user share.
 // 只有定义了此事件处理函数,右上角菜单才会显示“转发”按钮
 // 用户点击转发按钮的时候会调用
 // 此事件需要 return 一个 Object,用于自定义转发内容
 },
 // 监听 页面滚动 事件
 onPageScroll: function(){
 // Do something when page scroll
 // 返回 { scrollTop } 页面在垂直方向已滚动的距离(单位px)
 },
 // 监听 Tab 标签的点击事件
 onTabItemTap(item) {
 console.log(item.index)
 console.log(item.pagePath)
 console.log(item.text)
 },
 // Event handler.
 viewTap: function(){
 this.setData({
 text: 'Set some data for updating view.'
 }, function(){
 // this is setData callback
 })
 },
 customData: {
 hi: 'MINA'
 }
})

小程序开发入门

小程序开发注意要点

状态更新

  • 状态取值与更新类似于 React
  • 必须调用 this.setData 去更新状态
  • 必须使用 this.data.xxx 去获取状态值
  • 单次设置数据不能超过 1024kb
  • 状态的值不能是 undefined

路由跳转

小程序开发入门

wxml模板内用法

<navigator url = "../aaa/aaa">跳转到新页面</navigator>

<navigator url = "../aaa/aaa" open-type = "redirect">跳转到新页面</navigator>

<navigator url = "../aaa/aaa" open-type = "switchTab">跳转到新页面</navigator>

js用法

//保留当前页面,跳转到应用内的某个页面(最多打开10个页面,之后按钮就没有响应的)
wx.navigateTo({ 
 url:"../aaa/aaa"
})

 
//关闭当前页面,跳转到应用内的某个页面(这个跳转有个坑,就是跳转页面后页面会闪烁一下)
wx.redirectTo({ 
 url:"../aaa/aaa"
 })
 
//跳转至指定页面并关闭其他打开的所有页面(这个最好用在返回至首页的的时候)
wx.reLaunch({ 
 url:'../index/index'
})

//跳转到tabBar页面,并关闭其他所有tabBar页面
wx.switchTab({ 
 url:"/pages/aaa/aaa"
})

//返回上一页面或多级页面
wx.navigateBack({ 
 delta:1
})

配置在TabBar中的页面不能使用 Navigate 跳转,只能使用 wx.switchTab 跳转

页面底部的 tabBar 由页面决定,即只要是定义为 tabBar 的页面,底部都有 tabBar

调用页面路由带的参数可以在目标页面的onLoad中获取

数据绑定

需要使用花括号

组件属性
<view id="item-{{id}}"> </view>
 
控制属性
<view wx:if="{{condition}}"> </view>
 
关键字
<checkbox checked="{{false}}"> </checkbox>
 
嵌入式样式
<view style="color:{{color}};" />

列表渲染

<view wx:for="{{array}}" wx:for-index="idx" wx:for-item="itemName" wx:key="idx">
 {{idx}}: {{itemName.message}}
</view>
  • wx:for 指定遍历的数组
  • wx:for-indx 指定当前的索引
  • wx:for-item 指定当前的遍历的数据
  • wx:key 指定列项唯一标识

wx:key 可以取值 ` this` 代表循环项本身*

<switch wx:for="{{numberArray}}" wx:key="*this" style="display: block;">{{item}}</switch>

条件渲染

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

事件绑定与传参

  • bind:tap 不会阻止冒泡事件向上冒泡
  • catch:tap 可以阻止冒泡事件向上冒泡
  • capture-bind:touchstart 触摸类事件支持捕获阶段 事件可继续传递
  • capture-catch:touchstart 触摸类事件支持捕获阶段 捕获事件不能继教传递

事件参数只能使用 dataset 传递, data- 后面不能有大写,大写会被自动转为小写,有连字符,会被转成驼峰

<view data-alpha-beta="1" data-alphaBeta="2" bindtap="bindViewTap"> DataSet Test </view>
Page({
bindViewTap:function(event){
event.target.dataset.alphaBeta === 1 // - 会转为驼峰写法
event.target.dataset.alphabeta === 2 // 大写会转为小写
}
})

模板

使用 name 定义模板名称,使用 is 引用模板,使用 data 接收数据

<template name="msgItem">
<view>
<text>{{index}}:{{msg}}</text>
<text> Time:{{time}}</text>
</view>
</template>
<import src="../../components/msgItem/msgItem.wxml"/>
<template is="msgItem" data="{{...item}}"/>

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

引用模板的同时,如果有想着wxss,也要同时引用

模板的引用可以使用两种方式 import 与 include

include 导入纯模板,不含逻辑,相于拷贝

WXS

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

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

个人应用较少,详情查看 文档

WXSS

  • 使用 rpx 单位做屏幕适配,以 750 宽度做为参考
    如在 iphone6 下,屏幕宽度为 375, 750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素
  • 使用 @import 导入wxss,只支持相对路径

选择器支持

小程序开发入门

自定义组件

组件类似于页面,由 .js .wxml .wxss 组成

组件可以设置 slot 类似于 vue

Component({
 // 组件的配置
 options: {
 multipleSlots: true // 在组件定义时的选项中启用多slot支持
 },
 // 组件的属性 类似于 Vue 的 props
 properties: {
 placeholder: {
 type: String,
 value: '请输入关键词搜索'
 },
 myProperty2: String // 简化的定义方式
 /* ... */
 },
 data: {/* 私有数据 */},
 methods: { /* ... */ }
})

属性名使用规则

  • 属性名如果是 驼峰写法(propertyName),使用时应使用 连字符写法 (property-name)
  • 属性名不能以 data 开头,会被当作 data-xxx 做为dataset 处理
  • 属性名不能与 data 中的字段冲突

组件模板

<view class="wrapper">
 <slot name="before"></slot>
 <view>这里是组件的内部细节</view>
 <slot name="after"></slot>
</view>

组件样式

#a { } /* 在组件中不能使用 */
[a] { } /* 在组件中不能使用 */
button { } /* 在组件中不能使用 */
.a > .b { } /* 除非 .a 是 view 组件节点,否则不一定会生效 */

公共样式 app.wxss 以及 组件所在的页面样式 对组件本身无效

组件事件

// 绑定自定义事件
<component-tag-name bind:myevent="onMyEvent" />

触发自定义事件

<button bindtap="onTap">点击这个按钮将触发“myevent”事件</button>

使用 this.triggerEvent 触发自定义事件

Component({
 properties: {}
 methods: {
 onTap: function(){
 var myEventDetail = {} // detail对象,提供给事件监听函数
 var myEventOption = {} // 触发事件的选项
 this.triggerEvent('myevent', myEventDetail, myEventOption)
 }
 }
})

下面两个特性由于没有实践过,这里一笔带过,详情请查看相关文档

  • 使用 behaviors 实现类似 mixins 的功能
  • 使用 relations 关联其它组件

渲染HTML

分包加载

目前小程序分包大小有以下限制

  • 整个小程序所有分包大小不超过 4M
  • 单个分包/主包大小不能超过 2M

分包后,小程序默认先下载主包,当访问到分包的内容后,再异步加载分包展示

在 app.josn 中配置分包

{
 "pages":[
 "pages/index",
 "pages/logs"
 ],
 "subPackages": [
 {
 "root": "packageA",
 "pages": [
 "pages/cat",
 "pages/dog"
 ]
 }, {
 "root": "packageB",
 "pages": [
 "pages/apple",
 "pages/banana"
 ]
 }
 ]
}

分包的目录结构与 app.json 中一一对应

├── app.js
├── app.json
├── app.wxss
├── packageA
│ └── pages
│ ├── cat
│ └── dog
├── packageB
│ └── pages
│ ├── apple
│ └── banana
├── pages
│ ├── index
│ └── logs
└── utils

打包原则

  • 声明 subPackages 后,将按 subPackages 配置路径进行打包, subPackages 配置路径外的目录将被打包到 app (主包) 中
  • app (主包)也可以有自己的 pages (即最外层的 pages 字段)
  • subPackage 的根目录不能是另外一个 subPackage 内的子目录
  • 首页的 TAB 页面必须在 app (主包)内

分包与分包之间资源相互隔离,不能相互引用,但可以引用 app 及公共资源

兼容

旧版微信客户端不兼容小程序新功能

  • 接口判断 if(wx.openBluetoothAdapter) {}

  • 参数判断 if(wx.canIUse('showModal.cancel')){}

  • 组件判断 Page({ data: {canIUse: wx.canIUse('cover-view')) })

通过 wx.getSystemInfo 或者 wx.getSystemInfoSync 获取到小程序的基础库版本号

数据统计

在小程序中通过 小程序数据助手 应用可以查看运营相关数据

生态

模板源码

开发框架

Vue风格的小程序开发框架

腾讯云

小程序开发套餐

小程序的一些限制

  • 安卓端暂时不支持 Promise ,使用引用第三方 Promise 库
  • WebView 渲染并非原生渲染
  • 不能直接扩展原生组件
  • 不能操作 cookie
  • 依赖于浏览器环境的JS库不能使用,没有 window 、 document 对象
  • 小程序不能与公众号重名
  • 接口的合法域名不能超过10个( Nginx 转发)
  • 并发请求数不能超过5个( websocket )
  • 页面层级不能超过10层
  • 编译打包后的程序包不能超过 4M (图片和视频使用CDN资源)
  • wxss样式中不能使用本地图片,wxml中可以使用本地图片资源
  • 无法访问真实的DOM节点
  • 无法绑定原生事件
  • 更新发布需要提交审核
  • 本地数据存储的大小限制为 10MB
  • 同时只能打开 10 个页面,超过时 wx.navigateTo 不能正常打开新页面
  • 输入组件,只能通过 bind:blur 事件获取用户输入
  • 无法直接渲染原生的HTML(使用 wxParse 插件)
  • 样式不支持级联选择器
  • 不支持本地图片资源(支持网络图片或base64)
  • 不支持 http , 只支持 https
  • 原生组件层级最高,且无法使用css动画
  • 省市区不支持港澳台选择
  • 只能使用微信支付
  • 本地文件存储的大小限制为 10M

由于小程序更新频繁,以上说明可能并不一定准确(2018.1.25)

查看原文: 小程序开发入门

  • bluelion
  • beautifulpanda
需要 登录 后回复方可回复, 如果你还没有账号你可以 注册 一个帐号。