文章目录
- 1、引入 vant-weapp UI
- 2、配置小程序 tabBar
- 3、小程序登录授权流程
- 4、小程序支付(微信支付)
- 5、小程序分享
- 6、小程序打开内置地图(腾讯地图)
- 7、小程序打开app
- 8、小程序打开其他小程序
- 9、小程序获取当前地理位置
- 额外:选择地址
 
- 10、自动检测版本更新
- 11、企业微信中配置小程序
- 12、扫码、拍照、相册
- 13、配置客服
- 14、api 封装
- 15、本地存储封装
- 16、底部安全距离组件
- 17、表单校验工具封装
- 18、富文本编辑器 editor
- 19、小程序如何操作前一页的内容
- 其他
- 1、小程序在 IOS 部分机型循环列表的第33个元素上边框消失
- 2、使用 flex:1进行多行整体布局的时候,页面有点乱
- 3、小程序修改对象属性
- 4、小程序阻止冒泡
- 5、小程序生命周期顺序
- 6、小程序动态绑定
- 7、获取小程序 dom 节点信息:
- 8、小程序模拟器上自定义组件显示没问题,真机上不显示
- 9、初次扫码打开小程序接口数据都是空白,打开调试模式就可以正常显示
- 10、在使用扫码链接打开小程序时,配置的测试帐号,必须与当前请求的地址、参数、参数值完全一致,不然可能会扫码到404;
- 11、canvas优先级过高,覆盖其他标签问题
- 12、小程序自定义头部
- 13、小程序生命周期和跳转
- 14、小程序生成访问二维码
- 15、微信开发者工具模拟企业微信
- 16、小程序使用van-field点击之后输入框会先失去焦点再次点击才会聚焦,开发工具上是正常的
- 17、ios跳转失败问题
- 18、vscode 开发微信小程序
 
 
 
 
本文是在工作中开发小程序遇到的问题或者经验的一个总结,目的在于梳理清楚一些功能细节,加深对流程上的理解;
1、引入 vant-weapp UI
1、打开小程序项目的终端,执行 mpn init,初始化package.json 文件;
 2、执行 npm i @vant/weapp -S ,安装 vant-weapp 组件库,成功之后会生成一个 node_module 依赖包;
 3、在微信开发者工具上,左上角“工具” 点击 “构建npm” ,成功之后会生成 miniprogram_npm文件;
 4、将 app.json 文件的 “style”:"V2" 去掉,因为小程序新版基础组件强行加了许多样式,难以 覆盖;
 5、修改 project.config.json 文件:setting 对象下面
 
 6、使用:
 全局引入:在 app.json 中配置
"usingComponents": {
    "van-button":"@vant/weapp/button/index"
  },
局部引入:在页面对应的 json 文件中配置(同上)
2、配置小程序 tabBar
在 app.json 中配置
"tabBar": {
    "color": "#999999",
    "selectedColor": "#0071D0",
    "backgroundColor": "#ffffff",
    "list": [
      {
        "pagePath": "pages/index/index",
        "text": "首页",
        "iconPath": "",
        "selectedIconPath": ""
      },
      {
        "pagePath": "pages/me/index",
        "text": "我的",
        "iconPath": "",
        "selectedIconPath": ""
      }
    ]
  },
3、小程序登录授权流程
1、判断是否存在 token,存在则校验 token 有效性,有效则继续,无效则清空 token;
2、token 失效或者不存在则走登录流程,首先调用wx:openSetting(打开设置页面授权)判断用户是否已授权,未授权则让用户授权;
3、已授权则调用wx.login获取登录凭证 code,将 code 发送给服务器,获取 openid、session_key 等信息,存储在本地;
4、用户点击按钮(根据需要设置open-type)触发事件,获取 iv、encryptedData,可以校验一下 code 的时效性;
5、调取服务器接口,拿到 token 缓存起来;
// 定义 login.js 文件
//获取到openid, session_key等信息
const login = () => {
  return new Promise((resolve, reject) => {
    // 调用微信登录接口获取用户临时登录凭证 code
    wx.login({
      success: (res) => {
        if (res.code) {
          // 登录成功,将 code 发送到开发者服务器
          wx.request({
            url: 'https://example.com/login',
            data: {
              code: res.code
            },
            success: (res) => {
              // 获取用户唯一标识 OpenID 和会话密钥 session_key
              const { openid, session_key } = res.data;
              // 将用户信息存储到缓存中,生成自定义登录态
              wx.setStorageSync('openid', openid);
              wx.setStorageSync('session_key', session_key);
              resolve();
            },
            fail: (err) => {
              reject(err);
            }
          });
        } else {
          reject(res.errMsg);
        }
      },
      fail: (err) => {
        reject(err);
      }
    });
  });
};
// 判断用户是否已授权
const checkAuth = () => {
  return new Promise((resolve, reject) => {
    // 获取用户当前设置状态
    wx.getSetting({
      success: (res) => {
        // 判断用户是否已授权
        if (res.authSetting['scope.userInfo']) {
          resolve();
        } else {
           // 用户未授权,引导用户打开设置页面进行授权
		    wx.showModal({
		      title: '提示',
		      content: '检测到您未授权登录,请先进行授权。',
		      showCancel: false,
		      success: (res) => {
		        if (res.confirm) {
		          wx.openSetting({
		            success: (res) => {
		              if (res.authSetting['scope.userInfo']) {
		                // 用户已授权,可进行相关操作
		                resolve();
		              }
		            }
		          });
		        }
		      }
		    });
        }
      },
      fail: (err) => {
        reject(err);
      }
    });
  });
};
// 在需要登录的页面调用 login() 方法进行登录授权和判断用户是否已授权
onLoad(){
	login();
}
//下面是用户手动触发的getPhoneNumber方法
getPhoneNumber(e){
	//这里可以使用 wx.checkSession 校验一下code 的有效性
	//e 里面可以拿到iv、encryptedData;发送给服务器获取到登录token
}
我这里上服务器获取用户的信息之后用过接口返回;也可以用个wx.getUserInfo 来获取用户信息;
注意:在调用 wx.openSetting() 方法时,需要在小程序的 app.json 文件中添加相应的权限设置。例如,如果要使用用户信息组件,需要在 app.json 中添加如下代码:
"permission": {
  "scope.userLocation": {
    "desc": "获取你的地理位置信息"
  },
  "scope.userInfo": {
    "desc": "获取你的个人信息"
  }
}
4、小程序支付(微信支付)
资质:
1、小程序已完成实名认证:需要提交个人或企业相关资料进行审核,并通过后才能开通支付功能;
2、小程序已开通微信支付:小程序管理后台中,需要先开通微信支付功能,配置相关参数和密钥;
3、绑定微信商户号:必须关联商户号才能开通支付功能;
流程:
1、需要在微信支付商户平台中注册商户账号,并进行相关的资质认证和审核。通过审核后,可以获得微信支付的商户号、API密钥和证书等信息;
2、在小程序中申请微信支付功能,绑定商户号;
3、使用 wx.request 方法调用统一下单接口,获取预付单信息,将获取到的信息传递给wx.requestPayment方法发起支付请求;
wx.requestPayment({
  timeStamp: payParams.timeStamp,
  nonceStr: payParams.nonceStr,
  package: payParams.package,
  signType: payParams.signType,
  paySign: payParams.paySign,
  success(res) {
    console.log('支付成功', res);
  },
  fail(err) {
    console.log('支付失败', err);
  }
});
5、小程序分享
微信小程序提供了 wx.showShareMenu API,可用于开启小程序页面的分享功能。开启分享功能后,用户可以将小程序页面分享给其他用户或群聊。
1、在小程序页面中调用 wx.showShareMenu 方法,开启分享功能。可以在 onReady 生命周期函数中调用该方法。
onReady: function() {
  wx.showShareMenu({
    withShareTicket: true,
    success: (res) => {
      // 分享功能开启成功
    }
  });
},
2、在小程序页面中定义一个自定义按钮,用于触发分享操作。在该按钮的 bindtap 属性中绑定 onShare 方法。
<button type="primary" bindtap="onShare">分享</button>
3、在小程序页面中定义一个 onShare 方法,用于触发分享操作。在该方法中,调用 wx.shareAppMessage 方法生成分享参数,并打开分享界面。
onShare: function() {
  return {
    title: '分享标题',
    path: '/pages/index/index',
    imageUrl: '/images/share.png'
  };
},
4、在小程序页面中添加分享统计代码。可以在 onShareAppMessage 生命周期函数中调用后台接口,记录分享事件并上传数据。
onShareAppMessage: function(res) {
  const { from, target, webViewUrl } = res;
  // 调用后台接口记录分享事件
  // ...
  return {
    title: '分享标题',
    path: '/pages/index/index',
    imageUrl: '/images/share.png'
  };
},
第1和第4都可以开启右上角的分享,
6、小程序打开内置地图(腾讯地图)
uni.openLocation({
 	latitude: 31.230416, // 上海的纬度
  	longitude: 121.473701, // 上海的经度
  	name: '上海市', // 地点名称
  	address: '中国上海市黄浦区人民广场', // 地址的详细说明
  	scale: 18, // 缩放比例
  	success: function(res) {
    console.log('打开地图成功');
  },
  fail: function(err) {
    console.log('打开地图失败', err);
  }
});
在地图上显示指定位置的标记点,并且支持调用内置地图进行导航;打开地图后点击右下角导航图标会弹出选项弹窗,让用户选择使用哪一个地图应用程序进行导航;
7、小程序打开app
根据官方说明不能由小程序跳转至任意app,只能跳回app,也就是只能从app跳至小程序,再由小程序跳回app;小程序返回 app 需要用户主动触发,所以不由 API 来调用,需要用 open-type 的值设置为 launchApp 的 button 组件的点击来触发;
如果需要在打开 APP 时向 APP 传递参数,可以设置 app-parameter 为要传递的参数。通过 binderror 可以监听打开 APP 的错误事件。
<button open-type="launchApp" app-parameter="wechat" binderror="launchAppError">打开APP</button>
Page({
  launchAppError (e) {
    console.log(e.detail.errMsg)
  }
})
参考:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/launchApp.html
注意:
 1、小程序也不能打开手机默认浏览器;
8、小程序打开其他小程序
需要用户点击、需要确认跳转才可以打开另一个已发布的小程序,写文章时小程序之间跳转没有任何限制,可以随意跳转;
wx.navigateToMiniProgram({
  appId: 'wx1234567890', // 要打开的小程序的appId
  path: '/pages/index', // 打开的页面路径,如果为空则打开首页
  extraData: {
    foo: 'bar' // 需要传递给目标小程序的数据,格式为键值对
  },
  success(res) {
    console.log('打开小程序成功', res);
  },
  fail(err) {
    console.log('打开小程序失败', err);
  }
});
需要保证用户已经授权并登录了目标小程序,否则会导致跳转失败;路径传参可以在打开的页面中 onLoad 生命周期通过 options 获取;extraData 通过小程序的 app.js 通过 onLaunch、onShow 参数 e.referrerInfo 获取;
如果想返回之前小程序可以使用:wx.navigateBackMiniProgram 只有在当前小程序被其他小程序打开的时候才可以调用成功;
9、小程序获取当前地理位置
首先需要在 app.json 里面配置获取位置权限;(uni-app 需要在manifest.json 里面的 mp-weixin 里面设置)
"permission": {
    "scope.userLocation": {
      "desc": "你的位置信息将用于小程序内的定位服务"
    }
  }
请求授权和获取位置信息都是异步操作,需要在回调函数中处理结果。另外,如果用户拒绝授权或未授权时,会导致 wx.getLocation 方法失败;
// 请求授权
wx.authorize({
  scope: 'scope.userLocation',
  success: function() {
    // 授权成功,获取位置信息
    wx.getLocation({
      type: 'wgs84', // 坐标类型,默认为wgs84,可选gcj02
      success: function(res) {
        const latitude = res.latitude; // 纬度
        const longitude = res.longitude; // 经度
        const speed = res.speed; // 速度,单位m/s
        const accuracy = res.accuracy; // 位置精度
        console.log('获取位置信息成功', res);
      },
      fail: function(err) {
        console.log('获取位置信息失败', err);
      }
    });
  },
  fail: function() {
    // 授权失败,提示用户开启权限
    wx.showModal({
      title: '未授权地理位置信息',
      content: '请在设置中打开地理位置权限',
      showCancel: false,
      confirmText: '确定'
    });
  }
});
额外:选择地址
在小程序管理后台,「开发」-「开发管理」-「接口设置」中自助开通该接口权限;
wx.chooseAddress({
      success(res){
        console.log(res)
      },
      fail(err){
        console.log(err)
      }
    })
可以调起用户编辑收货地址原生界面;可以选择已有地址,也可以添加新地址;
10、自动检测版本更新
在 app.js 中
App({
  onLaunch() {
    this.autoUpdate();
  },
  globalData: {
    userInfo: null
  },
  //检测版本更新
  autoUpdate(){
    //检测当前设备是否可用getUpdateManager api
    if(wx.canIUse('getUpdateManager')){
      const updateManasger = wx.getUpdateManager();
      //检测是否有版本更新
      updateManasger.onCheckForUpdate(function(res){
        if(res.hasUpdate){
          wx.showModal({
            title: '更新提示',
            content: '需要重启小程序完成更新',
            success: (res) => {
              if (res.confirm) {
                //更新成功,强制重启小程序并使用新版本
                updateManasger.onUpdateReady(function(){
                  updateManasger.applyUpdate();
                })
                //更新失败,提示用户删除小程序重新进入
                updateManasger.onUpdateFailed(function(){
                  wx.showModal({
                    title: '更新提示',
                    content: '小程序更新失败,请您删除当前小程序,重新搜索打开!'
                  })
                })
              }
            }
          })
        }
      })
    }
  }
})
11、企业微信中配置小程序
1、登录企业微信后台:应用与小程序-小程序-关联小程序;或者登陆小程序后台:设置-关联设置-关联的企业微信;
 2、关联过程中需要小程序管理员授权;
 3、对小程序进行可见范围设置;这样企业微信成员就可以在工作台看到小程序了;
12、扫码、拍照、相册
要在小程序中实现扫码、拍照和相册功能,可以使用微信提供的 API 接口。以下是具体实现方法:
 1、扫码
 需要获取摄像头权限。可以通过 wx.authorize 接口请求用户授权,或者在 app.json 文件中设置 "permission": {"scope.camera": {"desc": "用于扫码"}}
scanCode: function() {
    wx.scanCode({
      onlyFromCamera: true,
      success(res) {
        console.log('扫码成功', res.result)
      },
      fail(res) {
        console.log('扫码失败', res)
      }
    })
  }
2、拍照
 同样需要获取摄像头权限;
wx.chooseMedia({
      count: 1,
      sizeType: ['original'],
      sourceType: ['camera'],
      success(res) {
        console.log('选择照片成功', res.tempFilePaths)
      },
      fail(res) {
        console.log('选择照片失败', res)
      }
    })
3、相册
 需要获取相册访问权限。可以通过 wx.authorize 接口请求用户授权,或者在 app.json 文件中设置 "permission": {"scope.writePhotosAlbum": {"desc": "用于保存图片到相册"}}
wx.chooseMedia({
      count: 1,
      sizeType: ['original'],
      sourceType: ['album'],
      success(res) {
        console.log('选择照片成功', res.tempFilePaths)
      },
      fail(res) {
        console.log('选择照片失败', res)
      }
    })
13、配置客服
移步到:微信小程序接入客服功能
14、api 封装
跟目录下新建文件夹 api ;
 1、新建 http.js :定义 baseUrl 方便后期维护;
 2、新建 request.js :
import { baseUrl } from "./http"
import storage from "../utils/storage";
module.exports={
  request:function(url, method, data){
    let fullUrl = `${baseUrl}${url}`;
    let token = storage.get('token');
    wx.showLoading({ title: '数据请求中' });
    return new Promise((resolve,reject)=>{
      wx.request({
        url: fullUrl,
        method,
        data,
        header:{
          'content-type': 'application/json', 
          'Authorization': 'Bearer' + token
        },
        success(res){
          wx.hideLoading();
          if(res.data.status == 200){
            resolve(res.data);
          }else if(res.data.status == 401){
            wx.showToast({
              title: '登录失效',
              icon: "none"
            })
            wx.reLaunch({
              url: '/pages/login/index',
            })
          }else{
            wx.showToast({
              title: res.data.message,
              icon: "none"
            })
            reject(res.data.message);
          }
        },
        fail(err){
          wx.reLaunch({
            url: '/pages/login/index',
          })
          wx.hideLoading();
          wx.showToast({
            title: err.errMsg,
            icon: "none"
          })
          reject(err);
        }
      })
    })
  }
}
3、新建模块 api 文件 (user_api)
import { request } from "./request"
module.exports = {
  user: (data) => request("user","get",data)
}
4、页面调用
const user_api = require("../../api/user_api");
user_api.user(data).then(res=>{
      console.log(res)
})
15、本地存储封装
在 utils 文件夹下新建 storage.js 文件
/**
 - 同步新增:get(key)
 - 同步修改、删除:set(key,value);只传递 key 就可以删除对应的key:value
 - 同步清空:clear()
*/
export default class storage {
  //同步获取
  static get(key){
    if(!key) return null;
    return wx.getStorageSync(key);
  }
  //同步存储、删除
  static set(key, value){
    if(!key) return;
    if(value == null || value == 'undefined'){
      return wx.removeStorageSync(key);
    }else{
      return wx.setStorageSync(key, value);
    }
  }
  //同步清空
  static clear(){
    return wx.clearStorageSync();
  }
}
16、底部安全距离组件
封装一个全局组件 safe,借助 env(safe-area-inset-botton)
<!--全局组件:底部安全距离-->
<view style="padding-bottom: env(safe-area-inset-botton);">
  <solt></solt>
</view>
17、表单校验工具封装
封装校验工具类
// 表单校验工具
export class validator {
  constructor(rules){
    this.rules = rules
    this.error= []
  }
  
  validate(form){
    this.error = [];
    Object.keys(form).forEach(key=>{
      let rule = this.rules[key];
      let required = this.rules[key].required;
      let message = this.rules[key].message;
      let maxLength = this.rules[key].maxLength;
      let fn = this.rules[key].fn;
      if(rule){
        if(required && !this.checkValue(form[key]) && !Array.isArray(form[key])){
          return this.error.push(message || ('请填写'+key));
        }
        //校验key是数组
        if(required && this.checkValueArr(form[key]).isNull && Array.isArray(form[key])){
          return this.error.push(message || (`请完善${this.checkValueArr(form[key]).key}信息`));
        }
        if(maxLength && this.max(form[key], maxLength)){
          return this.error.push(`最多可输入${maxLength}个字!`);
        }
      }
    })
    return this.error;
  }
  checkValueArr(arr){
    let isNull = false;
    let key = null;
    for(let i in arr){
      if(!arr[i].value){
        isNull = true;
        key = arr[i].name;
        break;
      }
    }
    return {isNull,key}
  }
  checkValue(value){
    return value.toString().length > 0;
  }
  max(value, maxLength){
    return value && value.length > maxLength;
  }
}
页面使用
let rules = {
  test:{
    required:true,
    message:"请输入用户名"
  }
}
let fromVal = new validator(rules);
利用 class 类,在new时将规则传入,在提交校验时执行下面操作,将form数据传入进行校验;
let err = fromVal.validate(this.data.form);
上面是我根据前人的思路根据自己的项目封装的一个方法,
18、富文本编辑器 editor
editor 是小程序提供的一个组件,搭配 EditorContext api 来实现工具栏的操作;
<!--富文本编辑器-->
<view style="margin: 20rpx; background: #f0f0f0;">
  <view style="display: flex; justify-content: space-around; padding-bottom: 20rpx;">
    <view class="item" bindtap="format" data-type="bold">加粗</view>
    <view class="item" bindtap="format" data-type="italic">斜体</view>
    <view class="item" bindtap="format" data-type="underline">下划线</view>
    <view class="item" bindtap="undo">撤回</view>
    <view class="item" bindtap="redo">恢复</view>
    <view class="item" bindtap="insertImg">插入图片</view>
    <view class="item" bindtap="clear">删除</view>
  </view>
  <editor 
  style="border-radius: 10rpx; border: 1rpx solid #ccc; background: #fff;"
  id="myEditor"
  placeholder="请输入"
  bindstatuschange="statusChange"
  bindready="onEditorReady"
  ></editor>
</view>
<van-button bindtap="submit">提交</van-button>
Component({
  properties: {
  },
  data: {
    editorCtx:''
  },
  methods: {
    // 初始化,获取到编辑器节点,缓存在data中,方便下面操作
    onEditorReady(){
      let that = this;
      let query = wx.createSelectorQuery();
      query.in(that).select("#myEditor").context();
      query.exec(res=>{
        that.editorCtx = res[0].context;
      })
    },
    undo(){
      console.log(1)
      this.editorCtx.undo();
    },
    redo(){
      this.editorCtx.redo()
    },
    insertImg(){
      let that = this;
      wx.chooseMedia({
        count:1,
        mediaType:["image"],
        sourceType:["album"],
        success(res){
          that.editorCtx.insertImage({
            src:res.tempFiles[0].tempFilePath
          })
        }
      })
    },
    clear(){
      this.editorCtx.clear()
    },
    submit(){
      this.editorCtx.getContents({
        success(res){
          console.log(res)
        }
      })
    },
    format(e){
      let type = e.currentTarget.dataset.type;
      this.editorCtx.format(`${type}`)
    }
  }
})
19、小程序如何操作前一页的内容
back(){
    const pages = getCurrentPages();
    const prePage = pages[pages.length-2];
    console.log(prePage)
    prePage.setData({
      msg:'sssss'
    })
    wx.navigateBack();
  }
想让上一页监听到,可以在后面调用一下前一页的方法;
其他
1、小程序在 IOS 部分机型循环列表的第33个元素上边框消失
1rpx 在IOS部分机型渲染像素点比较低,出现偶尔不显示的情况。可以设置为 1px 然后对边框进行缩放;
2、使用 flex:1进行多行整体布局的时候,页面有点乱
尽量避免多行整体布局使用 flex:1;因为这个1是针对剩余空间进行分配,而不是父元素的宽度;
3、小程序修改对象属性
let c = `arr[${i}].name`
this.setData({
	"obj.a":b,
	[c]:d
})
4、小程序阻止冒泡
用 catchtap 来绑定事件;
5、小程序生命周期顺序
应用:onLaunch onShow
 页面:onLoad onShow onReady
 组件:attached() -> ready() -> moved() -> detached()
6、小程序动态绑定
class="name {{isOk?'a':'b'}}"
style="height:{{nav}}rpx"
7、获取小程序 dom 节点信息:
页面:
var query = wx.createSelectorQuery();
query.select('.header').boundingClientRect()
query.selectViewport().scrollOffset()
query.exec((res) => {
	var listHeight = res[0].height; // 获取list高度
	this.setData({
		height:listHeight
	})
})
组件:
var query = wx.createSelectorQuery().in(this);
query.select('.header').boundingClientRect()
query.selectViewport().scrollOffset()
query.exec((res) => {
	var listHeight = res[0].height; // 获取list高度
	this.setData({
		height:listHeight
	})
})
方法放到 ready 周期里面,如果还获取不到,在用定时器包裹;
8、小程序模拟器上自定义组件显示没问题,真机上不显示
组件json中添加 “component”: true
9、初次扫码打开小程序接口数据都是空白,打开调试模式就可以正常显示
只需要在小程序后台,将服务端域名配置成合法域名
10、在使用扫码链接打开小程序时,配置的测试帐号,必须与当前请求的地址、参数、参数值完全一致,不然可能会扫码到404;
11、canvas优先级过高,覆盖其他标签问题
1、使用uni-app提供的 cover-view、cover-image等标签;
2、给canvas标签一个判断控制显示隐藏;
12、小程序自定义头部
在配置里面设置 navigationStyle:custom ,原生和uni-app 有区别;获取设备头部信息:uni.getSystemInfo({}),获取状态栏高度,导航栏高度;
13、小程序生命周期和跳转
1、跳转方式区别
navigateTo:跳转到下一页,保留当前页;
navigateBack:关闭当前页面,跳转到前一页;
redirectTo:关闭当前页面,跳转到其他页面;
reLaunch:关闭所有页面,跳转到某个页面;
switchTab:关闭所有非 tabBar 页面,跳转到 tabBar 页面;路径不可携带参数;
js 中使用方法 getCurrentPages() 可以获取当前页面战;
2、生命周期
onLaunch:小程序初始化完成触发,只触发一次;(获取用户信息)
onShow:小程序启动、后台进入前台触发;
onHide:小程序从前台进入后台触发;
onError:收集错误信息;
onPageNotFound:入口页面找不到时,通过它抱错,处理;
onLoad:页面初始化触发,一个页面只调用一次;(发送请求,初始化数据)
onShow:页面显示、后台进入前台触发;
onReady:页面初始化完成触发,只调用一次;
onHide:切入后台触发;
onUnload:页面卸载触发;
onPullDownRefresh:页面下拉刷新触发
onReachButton:
3、二者关系
navigateTo:onHide - onLoad - onShow - onReady
navigateBack:onUnload - onShow
redirectTo:onUnload - onLoad - onShow - onReady
14、小程序生成访问二维码
小程序后台,右上角-工具;输入扫码之后进入的页面路径;
15、微信开发者工具模拟企业微信
下载企业微信插件(设置-扩展设置-模拟器插件-企业微信模拟器),然后将小程序模式调整为企业微信小程序模式;
16、小程序使用van-field点击之后输入框会先失去焦点再次点击才会聚焦,开发工具上是正常的
使用的是 van-field 组件,可以检查组件的配置参数是否正确,例如 auto-focus 或 focus 参数是否设置为 true
17、ios跳转失败问题
页面跳转,ios偶尔会跳转失败,navigateTo成功和完成的回调都能打印出来;具体原因不明,在网络请求拿到结果后跳转时延迟1秒就可以降低失败概率,但是依然会出现跳转失败的情况;
 猜测可能是焦点异步有关系;
 http://shop.jisuapp.cn/pecial/a79256.html
18、vscode 开发微信小程序
安装插件 “微信小程序插件” ,用微信开发者工具创建小程序项目,然后用 vscode 打开;就可以开发代码了;



















