文章目录
一、用户授权流程
1.用户授权判断
通过mpvue.getSetting判断小程序是否获得权限
新建src\api\wechat.js
export function getSetting(auth, onSuccess, onFail) {
mpvue.getSetting({
success(res) {
// authSetting: 用户授权结果(是否包含对应权限)
if (res.authSetting[`scope.${auth}`]) {
onSuccess(res)
} else {
onFail(res)
}
},
fail(res) {
}
})
}
在src\pages\index\index.vue中检验授权
import {getSetting} from '../../api/wechat'
mounted() {
this.getSetting()
},
methods: {
getSetting() {
getSetting('userInfo', () => console.log('成功'), () => console.log('失败'))
},
2.用户申请授权
如果小程序未获得授权,我们需要提供用户主动申请授权的功能,微信规定获取用户信息,必须用户主动触发,此时我们需要借助button组件完成用户授权事件绑定,关键步骤:
- 新建src\components\base\Auth.vue:
<template>
<div class="auth-wrapper">
<div class="auth">
<div class="auth-info">
<div class="auth-img">
<ImageView src="https://www.youbaobao.xyz/mpvue-res/logo.jpg" round/>
</div>
<div class="sub-title">登录小慕读书</div>
<div class="title">全球好书免费读</div>
</div>
<button
class="auth-btn"
@getuserinfo="getUserInfo"
open-type="getUserInfo">
授权登录
</button>
</div>
</div>
</template>
<script>
import ImageView from './ImageView'
export default {
components: {ImageView},
methods: {
getUserInfo() {
this.$emit('getUserInfo')
}
}
}
</script>
<style lang="scss" scoped>
.auth-wrapper {
position: fixed;
left: 0;
top: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: #999999;
z-index: 1000;
.auth {
position: relative;
width: 270px;
height: 248px;
background: #f5f5f5;
border-radius: 18px;
.auth-info {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 22.5px;
.auth-img {
width: 74px;
}
.sub-title {
font-size: 13px;
color: #999999;
line-height: 18.5px;
margin-top: 18px;
}
.title {
font-size: 16px;
color: #333333;
font-weight: 400;
line-height: 22.5px;
margin-top: 3.5px;
}
}
.auth-btn {
position: absolute;
bottom: 0;
width: 100%;
height: 49px;
line-height: 49px;
font-size: 15px;
color: #FFFFFF;
background-image: linear-gradient(90deg, #1EA3F5 0%, #0F87FC 100%);
border-radius: 0 0 10px 10px;
}
}
}
</style>
注意@getuserinfo是小写的。。。
- 在src\pages\index\index.vue中调用Auth组件,并修改dom结构为如下:
<div>
<div class="home" v-if="isAuth">
<SearchBar />
<HomeCard/>
<HomeBannner/>
<div>
<HomeBook/>
<HomeBook/>
<HomeBook/>
<HomeBook/>
</div>
</div>
<Auth v-if="!isAuth"/>
</div>
....
import Auth from '../../components/base/Auth'
components: {....Auth},
data() {return {....isAuth: true}},
....
methods: {
getSetting() {
getSetting(
'userInfo',
() => {
console.log('成功')
this.isAuth = true
this.getUserInfo()
},
() => {
console.log('失败')
this.isAuth = false
})
},
关于getuserinfo和open-type的官方说明如下:
属性 | 说明 |
---|---|
open-type | 微信开放能力 |
bindgetuserinfo | 用户点击该按钮时,会返回获取到的用户信息,回调的detail数据与wx.getUserInfo返回的一致,open-type="getUserInfo"时有效 |
查看官方文档:授权 | 微信开放文档
3.获取用户信息
通过mpvue.getUserInfo获取用户信息
- 在src\api\wechat.js中新增如下方法:
export function getUserInfo(onSuccess, onFail) {
mpvue.getUserInfo({
success(res) {
console.log('res')
const { userInfo } = res
if (userInfo) {
onSuccess(userInfo)
} else {
onFail(res)
}
},
fail(res) {
console.log('res') // 直接抛出异常
}
})
}
- 在src\pages\index\index.vue中新增如下方法:
getUserInfo() {
getUserInfo(
(userInfo) => {
console.log(userInfo)
},
() => {
console.log('获取用户信息failed...') // 获取用户信息,抛出异常
}
)
},
为了使登录过程更加合理,我们将初始化部分综合到init()方法中:
mounted() {
this.init()
},
methods: {
init() {
this.getSetting()
this.getHomeData()
},
在src\api\wechat.js中新增如下两个方法,用来缓存用户授权信息:
export function setStorageSync(key, data) {
mpvue.setStorageSync(key, data)
}
export function getStorageSync(key) {
return mpvue.getStorageSync(key)
}
将setStorageSync和getStorageSync方法添加到getUserInfo的成功回调中:
getUserInfo() {
getUserInfo(
(userInfo) => {
console.log(userInfo)
setStorageSync('userInfo', userInfo)
const openId = getStorageSync('openId')
if (!openId || openId.length === 0) {
console.log('请求openId')
} else {
console.log('已获得openId')
}
},
() => {
console.log('获取用户信息failed...') // 获取用户信息,抛出异常
}
)
},
4.获取openId
由于每个用户在每个小程序都会获得唯一的openId,所以openId非常适合用作用户的唯一标识,获取openId我们需要通过官方提供的api auth.code2Session来获取,为了简化api调用,课程提供了该api的封装版本:API | 「小慕读书」官网
打开小程序管理平台:https://mp.weixin.qq.com/,登录并找到APP_ID和APP_SECRET添加到src\utils\const.js中:
export const APP_ID = 'wx6ca257b141a31ade'
export const APP_SECRET = 'a32f84636cfcdba9688f928da3e2cbb4'
在src\api\index.js中添加getOpenId方法来调用wx.login接口:
import { APP_ID, APP_SECRET } from '../utils/const'
export function getOpenId(code) {
return get(`${API_URL}/openId/get`, {
appId: APP_ID,
secret: APP_SECRET,
code
})
}
在src\api\wechat.js中添加getUserOpenId方法,调用getOpenId方法
export function getUserOpenId(callback) {
mpvue.login({
success(res) {
if (res.code) {
const {code} = res
// console.log('code' + code)
getOpenId(code).then(response => {
// console.log(response)
const { data: { data: { openid } } } = response
setStorageSync('openId', openid)
callback && callback(openid)
// console.log('openid:' + openid)
}).catch(err => {
console.log(err) // 直接抛出异常
})
} else {
console.log(res) // 直接抛出异常
}
},
fail(res) {
console.log(res) // 直接抛出异常
}
})
}
- 请求回来的response:
调试查看结果
- 清除缓存
- 重新运行小程序
- 授权登录
- 确定
可见控制台信息为如下:
- 再次重新运行小程序:
这时使用的openId是缓存当中的
代码中的APP_ID和APP_SECRET均为注册小程序时获取到的,对应自己的小程序(与开发者绑定)详细请看:查看微信公众号的AppID和AppSecret
这里推荐一个官方提供的工具:微信公众平台接口调试工具
5.用户登录
通过mpvue.login进行用户登录,登录后会获得code,该code可用于获取openId,但要注意code只能使用一次,用完即作废
6.用户注册
使用回调函数
现在既然已经有了openId,就可以在src\pages\index\index.vue中的getHomeData方法传入这个openId:
getHomeData(openId) {
getHomeData({openId}).then(response => {...})
...
},
接下来在src\pages\index\index.vue中的getUserInfo方法中定义一个变量onOpenIdComplete,将它传入getUserOpenId以实现动态获取openId:
getUserInfo() {
const onOpenIdComplete = (openId) => {
this.getHomeData(openId)
}
getUserInfo(
(userInfo) => {
// console.log(userInfo)
setStorageSync('userInfo', userInfo)
const openId = getStorageSync('openId')
if (!openId || openId.length === 0) {
getUserOpenId(onOpenIdComplete)
console.log('请求openId')
} else {
console.log('已获得openId')
onOpenIdComplete(openId)
}
},
() => {
console.log('获取用户信息failed...') // 获取用户信息,抛出异常
}
)
},
这里需要梳理一下里面这个回调:
- 点击授权登录
- 调用index.vue里的getUserInfo方法
- 执行src\api\wechat.js的getUserInfo方法
- 执行:getUserOpenId():授权登录后拿到openId传给回调函数callback
- 执行回调方法onOpenIdComplete(作为参数callback即回调函数)
- 带着openId去执行index.vue里的getHomeData,over
- 再次刷新
- 执行:else里面的onOpenIdComplete(openId),(直接拿到缓存里的openId)
- 带着openId去执行index.vue里的getHomeData,over
注册
获得openId后,我们可以通过该openId和用户信息在小慕读书中进行注册,课程提供了注册的api,立即查看:API | 「小慕读书」官网
- 在src\api\index.js中添加register方法来调用wx.login接口:
export function register(openId, userInfo) {
return post(`${API_URL}/user/register`, {
openId,
platform: mpvuePlatform, // 通过这个参数获取当前环境的platform(微信、支付宝、...)
...userInfo // 将userInfo数据打散传入
})
}
- 然后在src\pages\index\index.vue中的回调函数onOpenIdComplete中调用注册(这里需要给onOpenIdComplete再加一个参数userInfo,注意改动的地方)
getUserInfo() {
const onOpenIdComplete = (openId, userInfo) => {
this.getHomeData(openId, userInfo)
register(openId, userInfo)
}
getUserInfo(
(userInfo) => {
// console.log(userInfo)
setStorageSync('userInfo', userInfo)
const openId = getStorageSync('openId')
if (!openId || openId.length === 0) {
console.log('请求openId')
getUserOpenId(openId => onOpenIdComplete(openId, userInfo))
} else {
console.log('已获得openId')
onOpenIdComplete(openId, userInfo)
}
},
() => {
console.log('获取用户信息failed...') // 获取用户信息,抛出异常
}
)
},
- 这是运行小程序就会在控制台看到如下信息(授权登录和二次登录截图)
改造HomeCard中头像和昵称的数据源
- 删掉src\pages\index\index.vue的getHomeData方法里userInfo的模拟数据,改造之后如下:
this.homeCard = {
bookList: shelf,
num: shelfCount,
userInfo
}
- 为getHomeData多传一个参数userInfo,调用的地方也是如此
- 修改src\components\home\HomeCard.vue中数据源名称与接口传回的一致:
computed: {
avatar() {
return (this.data && this.data.userInfo && this.data.userInfo.avatarUrl) || ''
},
nickname() {
return (this.data && this.data.userInfo && this.data.userInfo.nickName) || ''
},
解决头像加载前占位图拉伸:
- 修改src\components\home\HomeCard.vue中ImageView标签的参数为:
<ImageView
:src="avatar"
round
height="100%"
mode="scaleToFill"/>
- 修改src\components\base\ImageView.vue渲染层的根标签:
<div class="image-view" @click="onClick" :style="{ height }">
- 授权组件中头像也是相同的问题,修改如下:
src\components\base\Auth.vue
<ImageView
src="https://www.youbaobao.xyz/mpvue-res/logo.jpg"
round
height="100%"
mode="scaleToFill"/>
样式中添加高度(受scaleToFill影响,否则高度为0)
.auth-img {
width: 74px;
height: 74px;
}
这样就一切正常了!
拓展:
二、授权组件
用户授权登录组件
组件名称 | 属性 | 参数 | 用途 | 默认值 |
---|---|---|---|---|
Auth | method | getUserInfo | 获取用户信息 | (空) |
三、做些优化
显示加载样式
在src\api\wechat.js中新增两个方法:
export function showLoading(title) {
mpvue.showLoading({
title,
mask: true
})
}
export function hideLoading() {
mpvue.hideLoading({)
}
这里是使用了微信自带的两个API:
使用样式
- 加载中样式在获取授权之后加载数据完成之前之前调用:
getSetting() {
getSetting(
'userInfo',
() => {
console.log('授权成功')
this.isAuth = true
this.getUserInfo()
showLoading('正在加载')
},
() => {
console.log('授权失败')
this.isAuth = false
})
},
- 隐藏加载在加载页面数据完成后和数据加载失败时调用:
getHomeData(openId, userInfo) {
getHomeData({openId}).then(response => {
...
hideLoading()
}).catch(() => {
hideLoading()
})
},