小程序开发指南

180 阅读6分钟

2019年参与了几个小程序项目的开发,一直在草稿箱中,今天整理发布一下,还有几个待更新的版本后续做小程序项目时再补充进来。 总结反思,不断提升,希望养成写文章的习惯,加油fighting~

官方文档

一、整体项目配置与搭建

  • 页面目录结构
├─behaviors  # 公共bahavior
  ├─ xxx.js
├─bin # node脚本
  ├─template # 公共模版文件
  ├─create.js # 执行脚本文件
├─common # 公共库
  ├─icon  # iconfont 图标库
  ├─style  # 公共样式
├─components # 公用组件库
├─images # 静态图片存放区
├─node_modules # 利用npm管理的所有包及其依赖
├─package.json # npm的配置文件
├─gulpfile.js # gulp配置文件
├─.eslintrc.js # eslint配置规则文件
├─service # 所有请求文件夹
  ├─request.js # 基础请求封装
  ├─ApiConfig.js # 所有api接口配置
  ├─homeService.js # 所有home页面的请求
├─util # 公用方法库
  ├─constant.js # 各种常量(不同环境域名+appid等)
  ├─util.js # 常用函数库
  ├─storage.js # 封装wx-storage-解决不同环境下缓存冲突的问题
  ├─promisify.js # 将微信api简化为promise
├─pages # 当前项目的源码,所有开发都在此目录中
    ├─home # 页面存放位置,以页面名称作为子文件夹
  • app.json配置

page数组的第一个页面为小程序一进入的起始页面

debug为true表示开启页面调试

{
  "pages": [
    "pages/transfer/transfer",
    "pages/memberHome/memberHome"
  ],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "小程序bar标题",
    "navigationBarTextStyle": "black"
  },
  "networkTimeout": {
    "request": 30000,
    "downloadFile": 30000
  },
  "debug": true
}
  • app.js入口常规设置
App({
	onLaunch() {
		const that = this
		/* 初次加载判断网络情况,无网络状态下根据实际情况进行调整 */
		wx.getNetworkType({
			success(res) {
				const networkType = res.networkType
				if (networkType === 'none') {
					that.globalData.isConnected = false
					wxShowToast('当前无网络')
				}
			}
		})
		/* 监听网络状态变化,可根据业务需求进行调整 */
		wx.onNetworkStatusChange(function(res) {
			if (!res.isConnected) {
				that.globalData.isConnected = false
				wxShowToast('网络已断开')
			} else {
				that.globalData.isConnected = true
				wx.hideToast()
			}
		})

		/* 小程序自动更新最新版本开始 */
		if (wx.canIUse('getUpdateManager')) {
			// 基础库 1.9.90 开始支持,低版本需做兼容处理
			const updateManager = wx.getUpdateManager()
			updateManager.onCheckForUpdate(function(result) {
				if (result.hasUpdate) {
					// 有新版本
					updateManager.onUpdateReady(function() {
						// 新的版本已经下载好
						wx.showModal({
							title: '更新提示',
							content: '新版本已经下载好,请重启应用。',
							success: function(result) {
								if (result.confirm) {
									// 点击确定,调用 applyUpdate 应用新版本并重启
									updateManager.applyUpdate()
								}
							}
						})
					})
					updateManager.onUpdateFailed(function() {
						// 新的版本下载失败
						wx.showModal({
							title: '已经有新版本了哟~',
							content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~'
						})
					})
				}
			})
		} else {
			// 有更新肯定要用户使用新版本,对不支持的低版本客户端提示
			wx.showModal({
				title: '温馨提示',
				content: '当前微信版本过低,无法使用该应用,请升级到最新微信版本后重试。'
			})
		}
	},
	onShow() {},
	globalData: {
		isConnected: true //网络是否连接
	}
})
  • gitignore配置(上传git忽略文件)
.idea/
.vscode/
node_modules/
npm-debug.log
.DS_Store
*.wxss 
!vantWeapp/*/*.wxss
package-lock.json

二、中转页面设计

思路: 把中转页面作为小程序的首页,专门处理登录,及针对不同环境、不同场景、用户身份进来小程序做对应页面转发

注意点:

  • 需跟后端沟通从模版消息进来小程序的地址对应参数
  • 注意区别微信小程序官方进入场景值
// transfer页面:
// js:
	/**
   * 生命周期函数--监听页面加载
   */
	onLoad: function(options) {
		console.log('transfer options: ', options) // 进入页面参数
		if (ENV !== 'MOCK') {
			this.loginAndRedirect(options)
		} else {
			// mock直接跳转用户首页
			wx.redirectTo({
				url: '/pages/memberHome/memberHome'
			})
		}
	},
	/**
	 * 微信登录后根据options跳转相应的页面
	 * @param {*} options 
	 */
	loginAndRedirect: function(options) {
		const that = this
		Promise.resolve()
			.then(() => {
				wx.showLoading({ title: '登录中...', mask: true })
			})
			.then(() => { // 检查登录状态
				return loginService.checkLogin().catch(() => {
					console.log('not login')
					return loginService.login()
				})
			})
			.catch((err) => {
				wx.showModal({
					title: '提示',
					content: err.message,
					showCancel: false,
					confirmText: '重试',
					success(res) {
						if (res.confirm) {
							that.loginAndRedirect(options)
						}
					}
				})
				throw err
			})
			.then(() => {
				that.redirectTarget(options)
			})
			.finally(() => {
				wx.hideLoading()
			})
	},
	// 判断根据参数跳转页面
	redirectTarget: function(options) {
		if (!!options && options.scene && String(options.scene).length > 4) {
			const scene = String(options.scene)
			const t = scene.substring(0, 4)
			let url = ''
			switch (+t) {
				case 1000: // 【商品明细】
					url = `/pages/goodDetail/goodDetail?scene={value}`
					break
				case 1001: // 【团长发货码】
					url = '/pages/memberDeliveryDetail/memberDeliveryDetail?id={value}'
					break
				default:
					wxShowToast('没有符合的页面')
					throw new Error('没有符合的页面')
					break
			}
			if (url.indexOf('{value}') > -1) {
				try {
					url = url.replace('{value}', scene.substring(4, scene.length))
				} catch (e) {
					throw e
				}
			}

			wx.redirectTo({ url })
		} else {
			// 正常流程
			const accessToken = getStorageSync(ACCESSTOKENINFO)
			if (!accessToken) throw new Error('无登录信息,请稍后再试')
	        wx.redirectTo({ url: '/pages/headIndex/headIndex' })
		}
	}

三、登录流程梳理

官方小程序登录介绍

官方UnionID机制

四、页面必要事件的处理与体验升级

事件方法api

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function() {
    Promise.resolve()
      .then(() => {
        wx.showNavigationBarLoading() // 在标题栏中显示加载
        // 下拉刷新时-重置页面数据!!!
        this.setData({pageNum: 1, list: [], isNextPage: true})
      })
      .then(() => {
        this.getInitData() // 初始化加载数据
      })
      .then(() => {
        wx.hideNavigationBarLoading() // 完成停止加载
        wx.stopPullDownRefresh() // 停止下拉刷新
      })
      .catch(err => {
        console.log('下拉刷新失败:', err)
      })
  }

五、处理mock、dev、test、prod不同环境的切换常量及域名配置

### 待更新

六、接口服务请求的封装

### 待更新

七、将微信api转为promise设计

### 待更新

八、引入第三方库的方式(ui组件库、插件库)

### 待更新

九、引入阿里图标库的方法

### 待更新

十、小程序缓存机制

### 待更新

十一、小程序支付功能实现

### 待更新

十二、小程序消息推送功能实现&&formId的收集与处理机制

模版消息推送参考1

批量收集formId参考2

十三、引导关注公众号实现的2种方式

注意: 1、支付成功,仅自动关注服务号,订阅号不可以!!! 2、<official-account></official-account> 当用户扫小程序码打开小程序时,开发者可在小程序内配置公众号关注组件,方便用户快捷关注公众号,可嵌套在原生组件内

引导关注公众号总结

official-account 组件关注

十四、小程序长按保存图片、上传、下载文件功能实现

十五、小程序授权机制

十六、小程序运行机制+更新机制

小程序官网介绍

十六、小程序中的简化技巧

  • 安装配置gulp,实时编译.less为.wxss
  • 写node脚本,快速高效建立page初始化模版页面和com初始化组件模版页面

十七、踩坑点~

  • 1、小程序开发版、体验版、正式版缓存storage数据冲突

解决:用环境变量区别存储的key

import { ENV } from '../utils/constant'
// 关键点:用环境变量区别存储的key
const getKey = (key) => {
	return `${ENV}-${key}`
}

// 同步获取缓存
export const getStorageSync = (key) => {
	return wx.getStorageSync(getKey(key))
}
// 同步存储
export const setStorageSync = (key, data) => {
	wx.setStorageSync(getKey(key), data)
}
// 同步删除缓存
export const removeStorageSync = (key) => {
	wx.removeStorageSync(getKey(key))
}
  • 2、正式版审核时遇到的坑
1、登录需要账号密码登录进去的,需提供一个测试账号密码供审核人员使用
2、如果首页内容过于简单(一般没有什么内容,只是处理登录中转这类),最好发版时备注一下

小程序审核踩坑

十八、小程序图片优化

小程序之图片懒加载1

小程序之图片懒加载2