头像昵称填写
当小程序需要让用户完善个人资料时,可以通过微信提供的头像昵称填写能力快速完善。
昵称填写
需要将 input 组件 type 的值设置为 nickname,当用户在此input进行输入时,键盘上方会展示微信昵称。
头像选择
需要将 button 组件 open-type 的值设置为 chooseAvatar,当用户选择需要使用的头像之后,可以通过 bindchooseavatar 事件回调获取到头像信息的临时路径。
然后调用
wx.uploadFile(文件上传)
wx.uploadFile({
url: wx.http.baseURL + '/upload', // 文档约定的文件上传的地址
filePath: avatar, // 回调中本地文件的位置地址(临时的http打头的地址)
name: 'file', // wx.uploadFile 要求必传。
header: { // 文档约定。 上传头像要携带token
Authorization: 'Bearer ' + token // 用户登录状态
},
formData: { // 接口文档的要求。可以不传
type: 'avatar'
},
success: (result) => {
//上传成功后打印
console.log(result)
// 传回JSON格式进行转换
const res = JSON.parse(result.data)
// 将转换后的地址存入本地头像的变量中即可
}
})
token无感刷新
token会过期,为啥?
简单两个字:安全
token过期了怎么办?
- 让用户重新登录。后台管理系统会这么做。
- 使用refreshToken做无感刷新
如何使用 refreshToken 做无感刷新
在响应拦截器中,判断请求A错误是否 401 ?
-
用refreshToken去请求某个接口(后端约定的),得到新的token和refreshToken 保存下来
-
用新token重新发 请求A 此时用户没有感知到错误。network面板中可以看到三个请求
请求A 401 → 2. refreshToken → 3. 请求A 正常
改进: 用refreshToken去请求某个接口也可能会报401!!!
在响应拦截器中,判断请求A错误是否 401 ?
是,
请求A是refreshToken?
是
回到login(同时携带当前页面路径),让用户重新登录,可以回到原来的位置
否
用refreshToken去请求某个接口(后端约定的),得到新的token和refreshToken 1. 保存下来 1. 用新token重新 发请求A 此时用户没有感知到错误。network面板中可以看到三个请求
请求A 401 → 2. refreshToken → 3. 请求A 正常
表单校验
自己写校验比较麻烦我们可以利用第三方插件 wechat-validate 来完成:
安装
npm install wechat-validate
使用说明:wechat-validate
// 在页面或组件中导入
import validate from 'wechat-validate'
Page({
// 通过 behaviors 注入 validate 方法
behaviors: [validate],
data: {
username: '张三',
password: '666666'
},
// 定义表单数据的验证规则
rules: {
mobile: [
{ required: true, message: '请填写手机号码!' },
{ pattern: /^1[3-8]\d{9}$/, message: '请检查手机号码是否正确!' },
],
code: [
{ required: true, message: '请填写短信验证码!' },
{ pattern: /^\d{6}$/, message: '请检查短信验证码是否正确!' }
]
},
getCode() {
// 单独只验证 mobile 这个数据
const { valid, dataKey, message } = this.validate('mobile')
if(!valid) wx.showToast({title: message, icon: 'none'})
// else do something
},
sendForm() {
// 验证码 rules 中定义的全部数据
const isAllValid = this.validate()
if(!isAllValid) return
// else request api
}
})
发送请求
wx.request用着不习惯? 可以试试第三方插件: wechat-http
安装
npm install wechat-http
使用说明
import http from 'wechat-http'
// 接口基础地址
http.baseURL = 'https://your.host.com'
// 请求拦截器
http.intercept.request = (options) => {
// 指定默认的头信息
const defaultHeader: AnyObject = {} //二挑一
const defaultHeader = {} //二挑一
// 权限认证
defaultHeader.Authorization = 'Bearer token'
// 合并头信息
options.header = Object.assign({}, defaultHeader, options.header)
// 拦截器处理后的请求参数
return options
}
// 响应拦截器
http.intercept.response = ({ statusCode, data, config }) => {
console.log(statusCode) // http 响应状态码
console.log(config) // 发起请求时的参数
// 拦截器处理后的响应结果
return data
}
// 挂载到 wx 全局命名空间
wx.http = http
// 也可作为模块导出
export default http
快捷方法
// GET 方法请求
http.get(url, data?)
// POST 方法请求
http.post(url, data?)
// PUT 方法请求
http.put(url, data?)
// DELETE 方法请求
http.delete(url, data?)
示例
Page({
async onLoad() {
await wx.http({url: '/path', methods: 'POST'})
// 或快捷方法
await wx.http.get('/path')
}
})
TypeScript 支持
import type { Http } from 'wechat-http'
// 扩展到全局对象 wx 中调用
declare global {
namespace WechatMiniprogram {
interface Wx {
http: Http
}
}
}
// 自定义业务接口返回数据的类型
declare module 'wechat-http' {
export interface ResponseResultData<T = any> {
code: number
message: string
data: T
}
}
wx.chooseMedia (拍摄或从手机相册中选择图片或视频)
const res = await wx.chooseMedia({ // 拍摄或从手机相册中选择图片或视频。
count: 1, // 图片上传数量 取值为1-9
mediaType: ['Image'],
// 上传文件类型 image 只能拍摄图片或从相册选择图片
// video 只能拍摄视频或从相册选择视频
// mix 可同时选择图片和视频
sizeType: ['compressed']
// 是否压缩所选文件 // compressed 压缩文件 //original 原始文件
})
使用腾讯位置服务
-
申请开发者密钥(key):申请密钥
-
开通webserviceAPI服务:控制台 ->应用管理 -> 我的应用 ->添加key-> 勾选WebServiceAPI -> 保存
(小程序SDK需要用到webserviceAPI的部分服务,所以使用该功能的KEY需要具备相应的权限)
-
下载微信小程序JavaScriptSDK,微信小程序JavaScriptSDK v1.1 JavaScriptSDK v1.2
-
安全域名设置,在小程序管理后台 -> 开发 -> 开发管理 -> 开发设置 -> “服务器域名” 中设置request合法域名,添加apis.map.qq.com
-
可以选择单独创建文件导入导出
import QQMAP from '../libs/qqmap-wx-jssdk' // 下载的JavaScriptSDK路径
export default new QQMAP({
key: 'RCJBZ-EZACV-HE4P7-5P6J2-SCZIK-IVFDU', // 创建文件是就把KEY值填写好 这样复用是不用来回寻找KEY值
})
// 导入位置服务实例
import QQMap from '../../../utils/qqmap'
Page({
onLoad() {
// 获取用户经纬度
this.getLocation()
},
// 获取用户的位置
async getLocation() {
// 调用小和序 API 获取用户位置
const { latitude, longitude } = await wx.getLocation()
this.getPoint(latitude, longitude)
console.log('终点位置:', latitude, longitude)
},
getPoint(latitude, longitude) {
// 逆地址解析(根据经纬度来获取地址)
QQMap.reverseGeocoder({ //提供由坐标到坐标所在位置的文字描述的转换。输入坐标返回地理位置信息和附近poi列表
keyword: '', //搜索关键词
location: [latitude, longitude].join(','),
success: result => {
// console.log(result)
// 过滤掉多余的数据
const points = result.data.map(({ id, title, _distance }) => {
return { id, title, _distance }
})
// 渲染数据
this.setData({ points })
},
})
}
})
wx.getLocation (获取当前的地理位置、速度)
示例代码
wx.getLocation({
type: 'wgs84',
success (res) {
const latitude = res.latitude
const longitude = res.longitude
const speed = res.speed
const accuracy = res.accuracy
}
})
或 (解构赋值)
async getLocation() {
const {latitude, longitude} = await wx.getLocation()
console.log(latitude, longitude)
}
wx.chooseLocation (打开地图选择位置)
使用方法直接调用即可(同上)
腾讯位置路线规划
onLoad({id}) {
console.log('保修id', id)
// const QQMAP = new QQMAP({
// key: 'RCJBZ-EZACV-HE4P7-5P6J2-SCZIK-IVFDU' // 必填
// })
QQMAP.direction({
mode: 'driving',
//路线规划选择,可选值:'driving'(驾车)、'walking'(步行)、'bicycling'(骑行),不填默认:'driving',可不填
from: '30.59982,114.3096',
//from参数不填默认 当前地址
to: '30.69982,114.2096',
// to 位置坐标,去哪
success: (res) => {
(官网为 function 则这里改动为箭头函数 需注意this的填写)
console.log(res, '地图回调');
// console.log(res.result.routes[0].polyline, '地图回调');
var ret = res;
var coors = ret.result.routes[0].polyline, pl = [];
//坐标解压(返回的点串坐标,通过前向差分进行压缩)
var kr = 1000000;
for (var i = 2; i < coors.length; i++) {
coors[i] = Number(coors[i - 2]) + Number(coors[i]) / kr;
}
//将解压后的坐标放入点串数组pl中
for (var i = 0; i < coors.length; i += 2) {
pl.push({ latitude: coors[i], longitude: coors[i + 1] })
}
console.log(pl, '地图成功回调')
//设置polyline属性,将路线显示出来,将解压坐标第一个数据作为起点
this.setData({
latitude:pl[0].latitude,
longitude:pl[0].longitude,
polyline: [{
points: pl,
color: '#FF0000DD',
width: 4
}]
})
},