UniApp 进阶功能实战
UniApp 多端登录、分包配置、分享功能等进阶技巧
一、微信一键登录
微信一键登录是小程序最常用的登录方式,通过获取用户手机号实现快速登录。
1.1 登录流程
用户点击登录按钮 → 微信授权弹窗 → 获取 code、encryptedData、iv
↓
后端解密获取手机号 → 登录成功,返回 token1.2 前端实现
typescript
// api/login.ts
// 调用后端微信登录接口
export function login(data) {
return request({
url: '/drone/user/user/wechat/login',
method: 'post',
data: data
})
}
// components/pop/popLogin.vue
<script setup>
import { ref } from 'vue'
import { login } from '@/api/login'
import { useUserStore } from '@/store/modules/user'
import { setToken } from '@/utils/auth'
// 定义组件事件,登录成功后关闭弹窗
const emit = defineEmits(['off'])
// 加载状态,防止重复点击
const isLoading = ref(false)
// 用户状态管理
const userStore = useUserStore()
/**
* 获取手机号回调
* @param e 微信返回的事件对象,包含 code、encryptedData、iv
*/
const getphonenumber = (e) => {
// 未授权手机号,直接返回
if (!e.detail.code) {
uni.showToast({ title: '取消登录', icon: 'none' })
return
}
isLoading.value = true
// 第一步:获取微信登录凭证 code
uni.login({
provider: 'weixin',
success: (loginRes) => {
// 第二步:调用后端登录接口,传入 code 和手机号加密数据
login({
code: loginRes.code,
encryptedData: e.detail.encryptedData,
iv: e.detail.iv
}).then((res) => {
// 第三步:登录成功,保存 token 和用户信息
setToken(res.data)
userStore.SET_TOKEN(res.data)
// 获取用户头像和昵称
uni.getUserInfo({
provider: 'weixin',
success: (infoRes) => {
userStore.SET_AVATAR(infoRes.userInfo.avatarUrl)
userStore.SET_NAME(infoRes.userInfo.nickName)
}
})
isLoading.value = false
emit('off')
}).catch(() => {
isLoading.value = false
uni.showToast({ title: '登录失败', icon: 'none' })
})
},
fail: () => {
isLoading.value = false
uni.showToast({ title: '微信登录失败', icon: 'none' })
}
})
}
</script>
<template>
<button open-type="getPhoneNumber" @getphonenumber="getphonenumber">
手机号快捷登录
</button>
</template>1.3 注意事项
| 场景 | 说明 |
|---|---|
| button 属性 | 必须设置 open-type="getPhoneNumber" |
| 加密数据 | encryptedData 和 iv 需传给后端解密 |
| 用户拒绝 | 用户拒绝时不会触发回调,需提示 |
二、多端小程序登录
UniApp 支持多个小程序平台,使用条件编译区分不同平台。
2.1 平台判断
typescript
#ifdef MP-WEIXIN // 微信小程序
#ifdef MP-TOUTIAO // 抖音小程序
#ifdef MP-BAIDU // 百度小程序
#ifdef MP-ALIPAY // 支付宝小程序
#ifdef MP-QQ // QQ 小程序2.2 统一登录入口
typescript
// utils/multiPlatformAuth.js
// 各平台后端登录接口
const loginApiMap = {
weixin: '/drone/user/user/wechat/login',
toutiao: '/drone/user/user/toutiao/login',
baidu: '/drone/user/user/baidu/login',
alipay: '/drone/user/user/alipay/login',
qq: '/drone/user/user/qq/login'
}
// 统一登录入口
export async function multiPlatformLogin(loginData) {
const platform = getCurrentPlatform()
switch (platform) {
case 'weixin':
return request({
url: loginApiMap.weixin,
method: 'post',
data: { ...loginData }
})
case 'toutiao':
return request({ url: loginApiMap.toutiao, method: 'post', data: loginData })
case 'alipay':
return request({ url: loginApiMap.alipay, method: 'post', data: loginData })
default:
return request({ url: loginApiMap[platform], method: 'post', data: loginData })
}
}
// 获取登录凭证
export function getLoginCode() {
return new Promise((resolve, reject) => {
const platform = getCurrentPlatform()
// 支付宝使用 my.getAuthCode
if (platform === 'alipay') {
my.getAuthCode({
scopes: 'auth_base',
success: (res) => resolve({ code: res.authCode, platform }),
fail: () => reject(new Error('获取授权码失败'))
})
return
}
// 其他小程序使用 uni.login
uni.login({
provider: platform,
success: (res) => resolve({ code: res.code, platform }),
fail: () => reject(new Error('获取登录凭证失败'))
})
})
}2.3 各平台差异
| 平台 | 登录 API | 授权方式 | 需后端配置 |
|---|---|---|---|
| 微信 | uni.login | button | AppID、Secret |
| 抖音 | uni.login | button | AppID、Secret |
| 百度 | uni.login | button | AppID、Secret |
| 支付宝 | my.getAuthCode | button | AppID、PrivateKey |
| uni.login | button | AppID、Secret |
三、分包配置
分包可以减小主包体积,提升小程序加载速度。
3.1 pages.json 配置
json
{
"pages": [
{ "path": "pages/index", "style": { "navigationBarTitleText": "首页" } },
{ "path": "pages/mine/index", "style": { "navigationBarTitleText": "我的" } }
],
"subPackages": [
{
"root": "pages-common",
"pages": [
{ "path": "common/kinds/kinds", "style": { "navigationBarTitleText": "分类" } },
{ "path": "common/orderView/detail", "style": { "navigationBarTitleText": "订单详情" } },
{ "path": "common/wallet/wallet", "style": { "navigationBarTitleText": "钱包" } }
]
},
{
"root": "pages-registered",
"pages": [
{ "path": "registered/agents", "style": { "navigationBarTitleText": "代理商" } },
{ "path": "registered/company", "style": { "navigationBarTitleText": "企业" } }
]
},
{
"root": "pages/lease",
"pages": [
{ "path": "productsDetail/productDetail", "style": { "navigationBarTitleText": "商品详情" } },
{ "path": "orderDetail/orderDetail", "style": { "navigationBarTitleText": "订单详情" } }
]
}
]
}3.2 分包跳转
typescript
// 跳转到分包页面
uni.navigateTo({
url: '/pages/lease/orderDetail/orderDetail?id=123'
})四、分享功能
分享是小程序重要的传播方式,各平台 API 不同,需用条件编译处理。
4.1 多端分享实现
typescript
// 微信小程序分享
#ifdef MP-WEIXIN
const onShareAppMessage = () => {
return {
title: '分享标题',
path: '/pages/index/index?id=123',
imageUrl: 'https://xxx.com/share.png'
}
}
const onShareTimeline = () => {
return {
title: '分享标题',
query: 'id=123'
}
}
#endif
// 支付宝小程序分享
#ifdef MP-ALIPAY
my.share({
title: '分享标题',
path: 'pages/index/index',
content: '分享摘要'
})
#endif
// 抖音小程序分享
#ifdef MP-TOUTIAO
const onShareAppMessage = () => {
return {
title: '分享标题',
path: 'pages/index/index?id=123'
}
}
#endif4.2 各平台支持情况
| 平台 | 分享给好友 | 分享到朋友圈 |
|---|---|---|
| 微信小程序 | onShareAppMessage | onShareTimeline |
| 支付宝小程序 | my.share | 不支持 |
| 抖音小程序 | onShareAppMessage | 不支持 |
| 百度小程序 | onShareAppMessage | 不支持 |
4.3 按钮分享
html
<button open-type="share">分享给好友</button>五、注意事项
5.1 登录注意事项
- 使用条件编译
#ifdef MP-WEIXIN判断平台 - 每个平台需单独对接后端接口
- code 只能使用一次,需重新获取
5.2 分包注意事项
- 分包间跳转使用绝对路径
root + path - 分包内资源只能分包内使用
5.3 分享注意事项
- 分享路径参数过长会影响显示
- 分享内容需符合平台规范
- 支付宝、百度、字节不支持朋友圈分享