Skip to content

UniApp 进阶功能实战

UniApp 多端登录、分包配置、分享功能等进阶技巧

一、微信一键登录

微信一键登录是小程序最常用的登录方式,通过获取用户手机号实现快速登录。

1.1 登录流程

用户点击登录按钮 → 微信授权弹窗 → 获取 code、encryptedData、iv

后端解密获取手机号 → 登录成功,返回 token

1.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.loginbuttonAppID、Secret
抖音uni.loginbuttonAppID、Secret
百度uni.loginbuttonAppID、Secret
支付宝my.getAuthCodebuttonAppID、PrivateKey
QQuni.loginbuttonAppID、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'
  }
}
#endif

4.2 各平台支持情况

平台分享给好友分享到朋友圈
微信小程序onShareAppMessageonShareTimeline
支付宝小程序my.share不支持
抖音小程序onShareAppMessage不支持
百度小程序onShareAppMessage不支持

4.3 按钮分享

html
<button open-type="share">分享给好友</button>

五、注意事项

5.1 登录注意事项

  • 使用条件编译 #ifdef MP-WEIXIN 判断平台
  • 每个平台需单独对接后端接口
  • code 只能使用一次,需重新获取

5.2 分包注意事项

  • 分包间跳转使用绝对路径 root + path
  • 分包内资源只能分包内使用

5.3 分享注意事项

  • 分享路径参数过长会影响显示
  • 分享内容需符合平台规范
  • 支付宝、百度、字节不支持朋友圈分享