微信小程序相关

678 阅读7分钟

全局配置 app.json

{
  //入口页面配置,如果不配置,默认使用pages第一项
  "entryPagePath": "pages/index/index",
  //页面配置
  "pages":[
    "pages/index/index",
    "pages/logs/logs",
    "pages/my/my"
  ],
  //导航栏配置
  "window":{
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle":"black",
    "navigationStyle":"default",
    "enablePullDownRefresh":true,
    "backgroundColor":"#000",
    "backgroundTextStyle":"light",
    "onReachBottomDistance": 20,
    "pageOrientation":"auto"
  },
  //底部tabBar配置
  "tabBar": {
    "color":"#ccc",
    "selectedColor":"#333",
    "backgroundColor":"#fafafa",  
    "borderStyle": "white",
    "position":"bottom",
    "custom": false,
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首页",
      "iconPath": "static/image/index-tab-deactive.png",
      "selectedIconPath": "static/image/index-tab-inactive.png"
    }
  ]
  },
  //配置全局组件
  "usingComponents":{},
  //网络超时配置
  "networkTimeout":{
    "request": 60000,
    "connectSocket":60000,
    "uploadFile":60000,
    "downloadFile":60000
  },
  //pc,ipad窗口自适应配置
  "resizable":true,
  //程序后台运行配置
  "requiredBackgroundModes": ["audio", "location"],
  "debug":true,
  "style": "v2",
  "sitemapLocation": "sitemap.json"
}

页面page.json配置

页面json配置会覆盖全局app.json中的配置

{
  "navigationBarBackgroundColor": "#ffffff",
  "navigationBarTextStyle": "black",
  "navigationBarTitleText": "首页",
  "backgroundColor": "#eeeeee",
  "backgroundTextStyle": "light",
  "usingComponents": {},
  "navigationStyle":"default",
  "backgroundColorTop":"#fff",
  "backgroundColorBottom":"#fff",
  "enablePullDownRefresh":false,
  "onReachBottomDistance": 50,
  "pageOrientation":"auto",
  "disableScroll":false
}

wxml语法

数据绑定

  • 绑定数据变量放在双大括号里面
<view> {{ message }} </view>
Page({
  data: {
    message: 'Hello MINA!'
  }
})
  • 属性绑定要在双引号里面,注意双引号和大括号之间不能有空格,不然会被解析成字符串
<view id="{id}"></view>
Page({
  data: {
    id: 0
  }
})

渲染列表

  • 通过wx:for绑定遍历数据,默认index为索引,item为每一项,wx:key传字符串代表item的属性,传*this代表item本身
<view wx:for="{{array}}" wx:key='id'>
  {{index}}: {{item.message}}
</view>
Page({
  data: {
    array: [{
      id:0,
      message: 'foo',
    }, {
      id:1,
      message: 'bar'
    }]
  }
})
  • wx:for传入一个字符串,会先解析成数组
<view wx:for="array">
  {{item}}
</view>
相当于
<view wx:for="['a','r','r','a','y']">
  {{item}}
</view>
  • wx:for-itemwx:for-index指定遍历项和索引的变量名
<view wx:for="{{array}}" wx:key="id" wx:for-item = "listItem" wx:for-index="itemIndex">
  {{itemIndex}}: {{listItem.message}}
</view>
  • block标签渲染包含多个节点的代码块
<block wx:for="{{[1, 2, 3]}}">
  <view> {{index}}: </view>
  <view> {{item}} </view>
</block>

条件渲染

小程序有两中条件渲染方式,wx:if指令还有hidden属性

  • wx:if
<view wx:if="{{condition}}"> True </view>
  • hidden属性
<view hidden="{{condition}}"> True </view>
  • wx:ifhidden的区别 wx:if是惰性,只有第一次渲染条件为真时才会渲染,但是切换代价较大,适用于切换频率较少的场景 hidden不管条件真假,都会渲染,只是切换显示与隐藏,适用于频繁切换的场景
  • block标签包裹多个节点条件渲染,block本身不被渲染

模板

通过template定义wxml模板片段,在不同的地方调用

  • 定义模板
//name值为模板名
//数据在使用模板时通过data属性传入
<template name="msgItem">
  <view>
    <text> {{index}}: {{msg}} </text>
    <text> Time: {{time}} </text>
  </view>
</template>
  • 使用模板
<template is="msgItem" data="{{...item}}"/>

wxss语法

wxss具有css大部分特性,但与css也有不同的地方

尺寸单位

小程序采用rpx作为尺寸单位,设计稿建议使用750的,容易换算

外部样式引入

通过@import加外部样式的相对路径导入

/** common.wxss **/
.small-p {
  padding:5px;
}
/** app.wxss **/
@import "common.wxss";
.middle-p {
  padding:15px;
}

内联样式

静态样式通过class定义,内联样式一般用在动态样式中

<view style="color:{{color}};" />

选择器

小程序支持css的部分选择器

  • id选择器
  • class选择器
  • 标签选择器
  • ::after和::before伪元素选择器

小程序内的javascript

执行环境

小程序使用javascript语言开发,执行在iOS,安卓,以及开发者工具,ES6在某些环境下没有得到完美的兼容,所以在项目设置中,勾选 ES6 转 ES5 开启此功能,就可以放心使用es6语法

模块化

小程序使用require.js实现模块化开发,使用module.export或者export导出模块,使用require导入模块

//utils.js
const formatTime = date => {
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hour = date.getHours()
  const minute = date.getMinutes()
  const second = date.getSeconds()

  return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
}
module.export = {
formatTime
}


//b.js
const util = require('../../utils/util')
Page({
  data: {
  },
  onLoad() {
    console.log('formatTime',util.formatTime(new Date()))
    //formatTime 2021/02/15 16:48:46
  }
})

作用域

  • 小程序中的变量和函数只在当前文件有效
  • 全局变量可以在入口文件app.js中进行设置
  • 当需要使用或者修改全局变量的时,通过使用全局函数 getApp() 获取全局的实例

程序

程序App构造器

// app.js
App({
  onLaunch: function(options) {
    console.log('onLaunch')
    console.log(this.globalData)
  },
  onShow: function(options) {
    console.log('onShow')
    console.log(options)
  },
  onHide: function() {
    console.log('onHide')
  },
  onError: function(msg) {
    console.log('onError')
  },
  globalData: {
    userInfo: null
  }
})

  • onLaunch 当小程序初始化完成时,会触发 onLaunch(全局只触发一次)
  • onShow 当小程序启动,或从后台进入前台显示,会触发 onShow
  • onHide 当小程序从前台进入后台,会触发 onHide
  • onError 当小程序发生脚本错误,或者 API 调用失败时,会触发 onError 并带上错误信息
  • 其他字段 可以添加任意的函数或数据到 Object 参数中,在App实例回调用 this 可以访问

页面

页面生命周期

Page({
  data: { text: "This is page data." },
  onLoad: function(options) { },
  onReady: function() { },
  onShow: function(options) { },
  onHide: function() { },
  onUnload: function() { }
})
  • onLoadonShow早于onReady
  • onLoadonShow携带了打开参数,用于页面传值等
  • 页面没销毁之前,onLoadonReady只触发一次,onShow每次页面展现都触发
  • onHide每次页面隐藏,并且没有销毁的时候触发
  • 页面销毁的时候触发onUnload 页面用户行为
Page({
   onPullDownRefresh: function() { },
  onReachBottom: function() { },
  onShareAppMessage: function () { },
  onPageScroll: function() { }
})

页面数据

data参数是页面第一次渲染时从逻辑层传递到渲染层的数据

Page({
  data: {
    text: 'init data',
    array: [{msg: '1'}, {msg: '2'}]
  }
})

数据更新通过setState方法,方法是异步的

this.setState({},callback)

页面路由

  • wx.navigateTo 保留当前页面,跳转其他非tabBar页面
  • wx.navigateBack 关闭当前页面,返回上一级页面
  • wx.redirectTo 关闭当前页面,跳转到其他非tabBar页面
  • wx.switchTab 关闭所有非tabBar页面,跳转tabBar页面
  • wx.reLaunch关闭所有页面,跳转其他页面

小程序登录

登录流程

1、在客户端调用wx.login()获取微信登录凭证code

2、将上一步获取的code,发送给后端,服务端调用微信接口,携带appId、appSecret、code参数,换取session_key、openIdsession_key不会发送给客户端,具有时效性,每次进入小程序先进行一次登录

3、在服务端生成自己的登录态标识(和openId、session_key关联),下发到客户端保存在本地存储storage,可以把自有登录状态保存,在调用服务端api时候,从storage中取出,请求中携带,如果登录状态过期,进行重新登录

登录第三方账号

首先是跟上面的步骤一样,拿到用户的唯一标识,接下来登录有两种方式,一个是用微信绑定的手机号登录,一个是手动输入账号登录,

  • 微信账号登录,需要手机号授权,然后把加密信息同用户标识发送给服务端进行登录
  • 手动输入账号,直接引导用户去登录页面,输入账号和验证码同用户标识发送给服务端进行登录

获取openId和unionId

获取openid

openid只是用户在某一应用下的唯一标识,如A用户在小程序的openid与A用户在公众号的openid是不一致的,获取方式如下

  • 通过wx.login()拿到code
  • code发送给服务端,服务端携带codeappidsecret换取openidsession_key 获取unionId

unionId是指用户在某个主体下的唯一标识,多个应用可以绑定统一主体,那unionId就是唯一的,获取的方法分几种情况

小程序缓存

缓存种类

  • 同步缓存
//写入缓存
wx.setStorageSync('key', 'value2')
//读取缓存
wx.getStorageSync('key')

  • 异步缓存
//写入缓存
wx.setStorage({
  key: 'key1',
  data: 'value',
  success: function(res) {},
  fail: function() {}
})
//读取缓存
wx.getStorage({
  key: 'key1',
  success: function(res) {},

  fail: function() { }

})

缓存特点

  • 同一个微信,不同小程序间缓存隔离
  • 同设备,登录不同微信用户缓存隔离
  • 缓存最多10mb,超出写入失败

使用场景

  • 缓存用户身份标识token
  • 缓存数据,预渲染。。。

小程序授权

小程序在使用微信敏感信息时候,需要提前授权,比如常用的是手机号授权,和用户信息授权,包括用户的头像、昵称、性别、省份、城市、openid、unionid信

具体步骤如下:

  • 1、小程序登录
  • 2、小程序端在特定位置放置授权按钮,用于引导用户进行授权。(用户点击后会有弹框)
  • 3、通过回调获取用户基本信息以及敏感信息加密数据

授权用户信息


<!-- 如果只是展示用户头像昵称,可以使用 <open-data /> 组件 -->
<open-data type="userAvatarUrl"></open-data>
<open-data type="userNickName"></open-data>
<!-- 需要使用 button 来授权登录 -->
<button wx:if="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权登录</button>
<view wx:else>请升级微信版本</view>
Page({
    data: {
        canIUse: wx.canIUse('button.open-type.getUserInfo')
    },
    bindGetUserInfo(e){
    const { detail = {} } = e
      const { iv, encryptedData, errMsg, userInfo } = detail
    }
 })

授权手机号

该接口针对非个人开发者,且完成了认证的小程序开放