微信小程序开发入门

写在前面

微信小程序出来也蛮久了,经过了市场的考验,已经站稳脚跟,融入到了各行各业,市场需求激增打来的是开发人员的紧俏,现在已经各大招聘网站也能看到有小程序开发的岗位在提供。恰逢公司有业务需要,现在入坑小程序开发,以一个初学者的身份把这一过程进行记录并分享,希望能在和朋友们的交流中提升自我。

其实但凡有一丢丢的编程基础,想入门都是很简单的事情,只要能跟着 官方文档 把流程走一遍,就算入门了。现在不比早期,官方文档被吐槽写的跟 shi 一样,所以还==非常推荐大家仔细读一下官方文档==。经常在交流的时候,看到有人连官方文档上写的清清楚楚的东西都拿来问,这是很可悲的事情。

有些问题官方文档上查不到,可以在官方 开发者社区 上输入关键字查一下,基本上前期遇到的问题都能得到解决。这两个地方都不能解决困惑的话,再去交流群求问或查看第三方论坛,如 很快-微信开发平台 。甚至说有的同学喜欢看视频,网上也能找到。当然也建议大家带着实践结论和个人理解去交流,这样容易得到答案,个人成长也会很快。

一、开发准备

不同于以往的项目,开发人员写完代码就可以了,在小程序开发,尤其是个人项目中,开发人员需要兼顾开发、运维、推广、客服等多个任务,虽然这一切都有微信提供的管理后台,但还是需要开发人员进行相关配置来保障项目的运行。

1. 小程序注册

可以把小程序理解为在微信大市场上注册的小商家,那么每个小程序就需要在 微信公众平台 注册账号用于管理。这个账号可以提供给我们小程序的唯一标示 AppId ,也可以帮助我们对小程序进行管理,协助我们完成编码开发以外的事情。注册方式主要两种:

1.1 官网注册

立即注册 -> 小程序

1.2 已有公众号后台(不支持个人类型公众号)

小程序 -> 小程序管理 -> 快速注册并认证小程序

补充:

- 注册账号要注意账号类型,选择小程序

- 小程序暂不支持更换主体(个人/企业),注册时类型不要选错

    - 个人类型小程序不支持不部分权限:如,微信用户手机号、微信支付、微信卡券等

- 同一邮箱不能注册多个公众平台账号,同一微信账号可以登录多个公众平台账号

    - 多人管理开发,均使用同一账号登录,微信扫码确认登录;其他人(非管理员)的微信账号可以通过配置 用户身份-登录权限 来拥有该能力

- 企业需要进行主体信息认证,周期较长,有 300 块费用,通过了还不能更改,所以要慎重填写

- 绑定开发者,并给与不同的权限

2. 开发工具

下载地址

基本使用简单,毕竟中文版,下载了看着引导创建一个 QuickStart  新项目,就能开撸了。或者下载这个 演示源码,当项目跑一下。整个开发工具还是挺清爽的,有种小霸王 N 合一的感觉。其中模拟器、编辑器、调试器都很直观,可以通过左上角按钮进行显隐操作,使用上搞过前端开发的都比较熟悉,此处不再赘述。说一下几个常用功能键:

2.1 预览、远程调试

两种真机调试的方案,各有不同的适用场景和注意事项:

- 预览

    - 需要拥有开发者权限的微信账号扫描才能使用,常用于他人在未发版情况下体验最新代码

    - 只有IDE登录微信账号扫描时,才和IDE共用一套缓存(此时IDE清缓存可以影响到真机)

    - 可以开启调试模式(微信右上角菜单 -> 打开调试),通过 vConsole 按钮展示真机调试区

    - 看不到请求具体信息,只能通过控制台打印

- 远程调试

    - 可以在PC上看到真机的控制窗口,常用于配合测试人员复现问题

    - 独立于IDE缓存,即账号A登录成功远程调试后,账号B进入远程调试,看到的是账号A的信息

    - 此时清缓存不能使用IDE清缓存,只能在远程调试窗口执行 wx.clearStore() 这种方式

    - 也没有 network

2.2 清缓存

开发和测试中需要经常模拟登录、授权的不同处理结果,此时就需要用到清缓存功能。IDE 提供了以下功能,可以一次全清也可以清除某一项,对应真机调试的实现如下:

- 清除代码缓存

    - 相当于真机调试时 - 删除小程序重新加载代码

- 清除授权缓存

    - 相当于真机调试时 - 微信右上角菜单 -> 关于xxx -> 右上角菜单 -> 设置 

- 清除数据缓存

    - 相当于真机调试时 - vConsole -> Wechat -> 点击wx.clearStorage()

- 清除网络缓存

    - 真机调试的网络缓存暂不清楚如何清除,静态资源通过增加时间戳

        - 注意同一个时间戳对应同一份资源缓存

        - Date.parse(new Date()).toString().slice(0, 8) 固定间隔 100s

        - Date.parse(new Date()) / (space * 60 * 1000)  根据 space 设置间隔分

- 清除登录缓存

    - 由于是静默登录,一般忽视该缓存

2.3 上传

开发完成后,小程序发布前,需要将代码上传到微信的服务器。关于上传有以下需要注意:

- 每个拥有开发权限的账号都可以上传,每个账号上传的代码是分开的

- 每个人只能保持一份上传的代码,二次上传会进行覆盖

- 微信公众平台 / 开发管理

    - 线上版本

    - 审核版本

        - 展示审核中和审核通过但未发布的版本

        - 同时只有一个版本进行展示

        - 首次审核周期较长,需要3-5个工作日,此后审核较快

        - 首次审核较为严格,需要注意很多问题,如诱导分享,详见[常见拒绝情形](https://developers.weixin.qq.com/miniprogram/product/reject.html#36-UI-%E8%A7%84%E8%8C%83)

    - 开发版本

        - 每个版本都可以设为体验版本,但同时只有一个体验版本,通过二维码供拥有体验者权限的人进行测试

        - 每个版本都可以提交审核,但同时只有一个审核中版本

        - 每个账号维护一份开发版本

2.4 详情(IDE右上角)

- 项目设置

    - 可以选择调试基础库,来测试兼容问题(存在兼容问题的 api 都写了最低版本,也可以查看 [历史更新日志](https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/uplog.html) 进行了解)

    - 未设置合法域名时,可以勾选 不校验安全域名 选项(线上域名一定要 TLS/SSL 认证)

- 域名信息

    - 查看合法域名

二、开发优化

1. promisify

https://github.com/stefanpenner/es6-promise

由于小程序提供的 API 都是回调风格的,在习惯了 ES6 promise 风格后,对回调嵌套不是很感冒,所以考虑进行包装处理。此处小程序提供的 Promise 有兼容问题,所以使用了 es6-promise 包来进行包装。

```

/**

* 将小程序的API封装成支持Promise的API

* @params fn {Function} 小程序原始API,如wx.login

*/

function wxPromisify(fn) {

  return (obj = {}, cb) => {

    return new Promise((resolve, reject) => {

      obj.success = (res) => {

        resolve(res);

      };

      obj.fail = (res) => {

        reject(res);

      };

      let taskObj = fn(obj);

      cb && (typeof cb == 'function') && cb(taskObj);

    })

  }

}

```

讨论:如何拿到原生 api 的返回值?

promise 给了我们在 success 回调中使用 return 关键字的能力,但没有 api 执行后的 return 失去了。此处使用 callback 抛出返回值,但是感觉并不优雅,有更好处理方式的请指点下我。

2. request

小程序提供的原生接口是 wx.request ,出于以下几点考虑,对其进行二次封装:

1. 小程序没有 cookie ,需要在 heaser 中携带 sessionId

2. 原生写法是回调风格,改造成 promise 风格

3. 需要公用部分业务相关的数据处理

4. 需要对请求进行统一拦截处理,如 loading 、timeout

3. 按钮节流阀

经常这种需求,按钮不能连续点击,所以提供一个节流功能的工具:

<pre>

function btnThrottle(self){

  selt.setData({

    buttonClicked: true 

  });

  setTimeout(() => {

    self.setData({

      buttonClicked: false

    })

  }, 500)

}

creat: function() {

  if(this.data.buttonClicked) return;

  util.btnThrottle(this);

}

</pre>

4. 代码清缓存

有时候在调试的时候需要经常保持代码最新,经常执行删除小程序还是很麻烦的,可以考虑使用下面方法:

```

onHide: function() {

  wx.setEnableDebug({

    enableDebug: true,

    success: () => {

      wx.setEnableDebug({

        enableDebug: false

      })

    }

  })

}

```

- 优点:可以清除代码缓存,每次打开都是重新加载

- 缺点:没办法保持退出时的状态,所以暂不考虑用到生产环境

三、常见问题

1. 登录逻辑

官方建议自己保存用户登录状态,不要频繁调用 wx.login ,否则会被限制登录。

有两种思路:

1. 先检查登录是否过期(wx.checSsession),在未过期的基础上执行其他请求(不是所有请求都需要登录,如世界排行)

2. 所有 api 请求都执行判断,如果返回未登录错误码(getUserInfo:fail auth deny),则申请授权(wx.authorize),授权成功继续请求,授权拒绝则强跳授权页(wx.openSetting)

目前登录判断:

1. wx.checkSession、wx.getStorage 检查登录是否过期和 sessionId 是否存在

2. 成功则判断结束,否则 wx.login、wx.getUserInfo 拿到用户信息

3. 成功则用拿到的信息向后台登录生成 sessionId,失败则申请授权操作(允许授权会继续,失败授权强跳授权页)

4. 成功拿到 sessionId 则保存 storage,失败提示网络问题

[最优体验:](https://mp.weixin.qq.com/s/JBdC-G9MwaptFjQeD9ujeA)

1. 调用 wx.login 获取 code,然后从微信后端换取到 session_key,用于解密 getUserInfo返回的敏感数据。

2. 使用 wx.getSetting 获取用户的授权情况

    - 如果用户已经授权,直接调用 API wx.getUserInfo 获取用户最新的信息;

    - 用户未授权,在界面中显示一个按钮提示用户登入,当用户点击并授权后就获取到用户的最新信息。

3. 获取到用户数据后可以进行展示或者发送给自己的后端

2. 路由跳转相关

系统 api 和 navigator 组件支持新开、重定向、返回、tab切换、重启动五种方式。读懂路由出入栈规则,可以帮你较好的处理跳转问题。但归根结底我们还是应该避免过于复杂的跳转逻辑,防止分享进入时的路由跳转问题。

有一种情况需要格外注意,在实现后退功能的时候,可能已经没有办法后退了(如分享卡片进入或已经退出当前页面但代码还在执行),此时执行 wx.navigateBack 会闪退。

```

// 兼容处理不同打开方式的后退

function toHome() {

  let pageCount = getCurrentPages().length;

  if(pageCount > 1) {

    wx.navigateBack({

      delta: 1

    })

  } else {

    wx.redirectTo({

      url: '/pages/home/index'

    })

  }

}

```

需要注意的是 tab 切换时的路由出入栈规则:

- tab a 到 tab b 相互切换时,触发的是 onHide 和 onShow(第一次切换会有 onLoad)

- tab a 的子页面切到 tab b 时,会把所有 a 的子页面 onUnload

3. 数据共享的实现

1. url传值 - 基于页面 - 适合少量值传递

```

wx.navigateTo({

  url: '/page/home/index?id=' + id

})

onload: function(opt) {

  console.log(opt.query)

}

```

2. storage - 基于本地缓存 - 适合大量值传递

注:

- 同一个微信用户,同一个小程序 storage 上限为 10MB

- localStorage 以用户维度隔离,同一台设备上,A 用户无法读取到 B 用户的数据

- 不建议将关键信息全部存在 localStorage,以防用户换设备的情况

[官方文档-api-数据缓存](https://mp.weixin.qq.com/debug/wxadoc/dev/api/data.html)

3. 全局 App - 基于内存

```

getApp().globalData.xxx

```

4. 退出当前页面后,代码还在执行

由于用户退出页面的操作具有不可控性,所以随时都可能出现代码不在当前页面执行的情况,而这种情况并不是我们想要看到的。所以需要对这种情况进行处理,保证代码执行稳定可控。常见的有异步请求、定时器。所以最基本的要求就是在退出页面是执行以下操作:

```

onUnload: function () {

    // 中断请求

    if (wx.canIUse('requestTask.abort')) {

      this.abortInit && this.abortInit.abort();

    }


    // 清理定时器

    clearInterval(this.xxxTimer);

    // 重置数据

    self.setData({

        //...

    });

  },

```

但总有漏网之鱼,在开发中我就遇到过,请求中断了,定时器清理了以后还在执行的情况。出现这种情况第一感觉并没有清理成功,API 执行出现了问题。

后来测试多次发现,并非 API 的锅,而是因为在未能中断的异步操作中触发了新的异步操作,而新的异步操作已经无法控制中断。如:某个 request 请求没能 abort 中断,该操作的回调中又调起了另一个 request 或 setTimeout ,此时场面失控了。

所以,流程清晰可控是必须的,各位在处理业务逻辑的时候一定要注意此类问题的出现。

5. share

作为非常重要的一个推广途径,用户分享自然是个很重要的功能点,小程序提供了相关的 API ,在使用中遇到以下问题并记录:

1. 分享最终执行的是 onShareAppMessage 对应的函数,相关的逻辑在其中处理

2. 分享的参数 imageUrl 存在低版本兼容问题,设置为 null 不能实现默认截屏, '' 可以截屏

3. 分享可以携带参数,写在 path 参数中即可,同 url 中的 query

    - 如果需要获取该参数,可以在 onShow 的参数 options 中获取到

4. 场景需要:分享到群判断,并判断是否群分享进入

    - 先设置带 shareTicket 的转发

        ```

        wx.showShareMenu({

            withShareTicket: true

        });

        ```

    - 在分享的成功回调函数中判断 shareTickets 群标识,存在即为分享到群

    - 获取场景值(onShow 的参数 options 中 scene),判断进入方式,常用场景值:

        - 1007:单人对话小程序卡片

        - 1036:App 分享消息卡片

        - 1044:群分享小程序卡片

6. 自定义分析

产品的良性发展自然少不了运营进行数据分析,常规做法是进行埋点统计。而小程序已经提供给用户一套相对来说比较完善的数据分析功能,可以登录微信公众平台 -> 数据分析查看,也可以通过小程序助手(官方小程序)便捷查看,当前前提是需要账号拥有数据分析的权限。

虽然官方提供的数据分析已经满足大部分需求,但是实际生产中肯定还需要定制数据分析,这里也有提供自定义分析。实现起来就是,先在微信公众平台进行自定义分析的事件注册,如果选择 API 上报则还是需要进行埋点配合。以下对自定义分析作简要说明:

1. 最低版本

  - 自定义数据上报仅对微信6.5.4及以上版本生效,涉及时间为 2017-01-23 以后更新即可

2. 新建事件

  - 事件名称

    - 英文名称:用于 API 上报

    - 中文名称:用户管理后台

  - 配置信息

    - 动作触发

      - trigger

        - click

        - 生命周期

        - share

        - switchTab

      - action

        - 一次性

        - 分步骤

      - page

        - app 层面的不用设置,默认 ANY_PAGE

      - element

        - click 需要触发元素,类或id选择器

      - data

        - 收集数据源,有默认字段和自定义字段

        - 自定义字段

          - 默认是从 page 实例的 data 中获取,字段名用于统计显示,字段值是指 data 中的 key

          - 也可以选择其他数据,看文档(渲染出来的list 、 wxml中的data-、 app实例的数据、系统属性)

    - API上报

      - 字段信息可以不填

      - 可自动生成代码

    - 二者的选择

      - 根据实际情况来,有时候点击满足不了要求

3. 测试事件

  - 保存并测试

  - 连续测试有时候测不到数据,不要担心,退出公众平台账号重新登录再测

4. 发布事件

  - 保存并发布

7. 微信服务通知

场景需求:开发者希望主动发送信息给用户

说明:该功能不建议频繁发送信息,可能会被用户主动拒收,而且该功能需要用户本人在微信体系内与页面有交互行为后触发(主动触发)

重点:获取用户的 formid

实现:

1. 必须通过 form 组件提交才能获取 formid

2. form 组件设置 report-submit='true'

3. form 组件添加 bindsubmit 事件, event.detail = {value: {'name': 'value'}, formId: ''}

4. 必须用户手动触发提交表单,不能 js 模拟提交,即必须有按钮

8. 小程序互相跳转

- 基础库 1.3.0 开始支持,低版本需做兼容处理

- iOS 微信客户端 6.5.9 版本开始支持,Android 客户端即将在 6.5.10 版本开始支持,请先使用 iOS 客户端进行调试

注:需要关联同一公众号

写在最后

以上内容并不能帮助大家熟练完成小程序开发,只是简单入门、踩坑记录、常见业务场景处理,还有非常多自己还没踩到的东西,如自定义组件、插件、分包加载都还没使用,API 也只用了有限的几个,比较重要的 微信支付 也未使用,后面用到了再一一记录。写出来方便大家快速接入小程序,也是自己的学习总结,有描述错误或不完善的地方,还请大家能够和我联系,相互学习交流。

问个问题:为啥我的代码片段展示出来和别人的不一样呢?```没用错啊

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容