久滴直播电商平台 · 技术博客系列 第 11 篇

🔖 标签:UniApp 跨端开发 小程序 H5

前言

直播电商产品的用户端需要覆盖多个平台——iOS App、Android App、微信小程序、H5 网页。如果每个平台都独立开发,人力成本和维护成本都会翻倍。

久滴直播电商平台选择 UniApp 作为跨端方案,一套代码同时编译到微信小程序、H5 和 App 三端。本文将分享这套方案在直播电商场景下的分包架构、nvue 原生渲染、组件化设计和多环境配置等实践经验。

目录

  1. 为什么选 UniApp?
  2. 分包架构设计
  3. nvue 原生渲染:直播详情页的性能优势
  4. 组件化设计:pkg-live 的 20+ 组件
  5. Hooks 封装:直播状态管理
  6. 多环境配置与 API 对接

1. 为什么选 UniApp?

常见的跨端方案对比:

方案 优点 缺点
Flutter 性能好,UI 一致 不支持小程序,生态偏原生
React Native 社区大,性能好 不支持小程序,学习成本高
UniApp 全平台覆盖,Vue 生态 性能略逊原生,部分 API 限制
Taro React 生态,支持多端 社区不如 UniApp 活跃

对于直播电商场景,UniApp 的优势在于:

  • 全平台:一套代码编译到微信小程序、H5、iOS、Android
  • Vue 生态:团队已有 Vue 经验,上手成本低
  • nvue 原生渲染:对性能要求高的页面(如直播详情页)使用原生渲染
  • 条件编译#ifdef / #ifndef 处理平台差异

2. 分包架构设计

微信小程序对主包大小有 2MB 限制,超过限制需要用分包。久滴 UniApp 端采用业务分包设计:

{
  "pages": [
    { "path": "pages/index/index" }
  ],
  "subPackages": [
    {
      "root": "pages/pkg-mall",
      "pages": [
        { "path": "mall-classify/index" },
        { "path": "goods-detail/index" },
        { "path": "submit-order" },
        { "path": "shopping-cart" }
      ]
    },
    {
      "root": "pages/pkg-order",
      "pages": [
        { "path": "order-list" },
        { "path": "order-detail" },
        { "path": "aftersale-apply" }
      ]
    },
    {
      "root": "pages/pkg-live",
      "pages": [
        { "path": "live-list" },
        { "path": "live-detail" },
        { "path": "live-playback" }
      ]
    },
    {
      "root": "pages/pkg-info",
      "pages": [
        { "path": "info-detail" },
        { "path": "video-detail" },
        { "path": "info-list" }
      ]
    },
    {
      "root": "pages/pkg-coupon",
      "pages": [
        { "path": "coupon-list" },
        { "path": "coupon-center" }
      ]
    }
  ]
}

分包策略:

  • 主包:只放首页和公共组件,保持尽量小
  • pkg-mall:商城相关(商品分类、详情、购物车、下单)
  • pkg-order:订单相关(列表、详情、售后)
  • pkg-live:直播相关(列表、详情、回放)
  • pkg-info:资讯内容
  • pkg-coupon:优惠券

每个分包独立加载,用户进入对应功能时才下载相关代码,首屏加载速度大幅提升。

3. nvue 原生渲染:直播详情页的性能优势

UniApp 默认使用 WebView 渲染页面。对于直播详情页这种需要同时播放视频流、渲染弹幕、展示商品列表的高性能场景,WebView 的性能可能不够理想。

久滴平台将直播详情页使用 .nvue(native vue)格式,启用原生渲染:

pages/pkg-live/
├── live-list.vue           # 直播列表(WebView 即可)
├── live-detail.nvue        # 直播详情(nvue 原生渲染)★
├── live-playback.vue       # 直播回放
└── components/
    ├── live-chat.vue       # 弹幕聊天组件
    ├── popup-prods.vue     # 商品列表弹窗
    ├── live-detail-item.vue # 直播间卡片
    └── ...

nvue 的优势:

  • 视频播放更流畅:原生 <video> 组件直接使用系统播放器
  • 弹幕渲染不卡顿:原生 List 组件复用视图,不会因消息量大而卡顿
  • 滑动切换更顺滑:原生 List 的上下滑动切换直播间体验接近原生 App

同时,通过条件编译处理 H5 端的差异:

<!-- App/小程序端:使用原生 video -->
<!-- #ifndef H5 -->
<video
  :src="src"
  :controls="false"
  :show-fullscreen-btn="false"
  object-fit="cover"
/>
<!-- #endif -->

<!-- H5 端:使用 TCPlayer Web SDK -->
<!-- #ifdef H5 -->
<view :id="containerId" class="tcplayer-container" />
<!-- #endif -->

4. 组件化设计:pkg-live 的 20+ 组件

直播分包包含 20+ 个组件,按功能分组:

components/
├── adapter-list.vue          # 直播间列表适配器
├── adapter-swiper.vue        # 直播间轮播适配器
├── live-chat.vue             # 弹幕聊天组件(核心)
├── live-detail-item.vue      # 直播间商品卡片
├── live-options.vue          # 直播间操作栏
├── popup-prods.vue           # 商品列表弹窗
├── popup-comment-input.vue   # 评论输入弹窗
├── popup-audience.vue        # 观众列表弹窗
├── popup-more-live.vue       # 更多直播弹窗
├── msg-product.vue           # 商品消息卡片
├── host-audience.vue         # 主播/观众切换
├── introducing-ani.vue       # 商品讲解动画
└── more-live.vue             # 更多直播入口

每个组件都有独立的 .scss 样式文件,实现了样式隔离和可复用性。

弹幕组件的消息处理

live-chat.vue 是直播间最核心的交互组件,处理弹幕消息的接收、去重、渲染和滚动控制:

const onGetMsgList = async (list: any[]) => {
    // 过滤当前群的消息
    const filteredMsgList = list.filter((item) => item.to === curGroupId.value)
    for (const item of filteredMsgList) {
        const targetItem = msgList.value.find((msg) => msg.ID === item.ID)
        // 去重 + 非空判断
        if (!targetItem && item.payload?.text) {
            const isAtBottom = await isScrollAtBottom()
            msgList.value.push({
                ID: item.ID,
                userName: item.nick || '未知用户',
                msg: item.payload.text,
            })
            // 只有用户处于底部时才自动滚动
            if (item.isSelfMsg || isAtBottom) {
                setScrollToBottom()
            }
        }
    }
}

5. Hooks 封装:直播状态管理

useLiveRoom.ts 封装了直播间的状态管理逻辑:

// hooks/useLiveRoom.ts
export function useLiveRoom() {
    const chat = ref<any>(null)
    const currentLiveIndex = ref(0)
    const liveList = ref<ILiveItem[]>([])

    // 进入直播间群
    const enterLiveRoom = async (index: number, oldIndex: number) => {
        const oldLiveItem = liveList.value[oldIndex]
        const liveItem = liveList.value[index]

        // 退出旧群
        if (oldLiveItem?.streamName) {
            await imHook.exitLiveRoom(oldLiveItem.streamName)
        }
        // 加入新群
        if (liveItem?.streamName) {
            await imHook.enterLiveRoom(liveItem.streamName)
        }
    }

    // 滑动切换直播间
    const handleListScroll = (event: any) => {
        uni.$emit(GlobalEventEnum.LIVE_SWIPING)
        if (!event.isDragging) {
            const i = Math.round(Math.abs(event.contentOffset.y) / windowHeight)
            if (i !== currentLiveIndex.value) {
                const old = currentLiveIndex.value
                currentLiveIndex.value = i
                enterLiveRoom(i, old)
            }
        }
    }

    return { chat, currentLiveIndex, liveList, handleListScroll }
}

直播间切换时的播放器懒加载也很关键:

const onTimeUpdate = () => {
    if (!props.isCurrent) pause()  // 非当前页自动暂停播放
}

6. 多环境配置与 API 对接

UniApp 通过 .env 文件管理不同环境的配置:

# .env.development
VITE_API_BASE_URL=http://localhost:48080

# .env.production
VITE_API_BASE_URL=https://api.kudi.net.cn

API 调用封装在统一的请求模块中:

// utils/request.ts
const http = uni.$uv.http

http.interceptors.request.use((config) => {
    const token = uni.getStorageSync('token')
    if (token) {
        config.header.Authorization = `Bearer ${token}`
    }
    return config
})

http.interceptors.response.use((response) => {
    const { code, data, msg } = response.data
    if (code === 0) return data
    uni.showToast({ title: msg, icon: 'none' })
    return Promise.reject(new Error(msg))
})

总结

本文分享了久滴直播电商平台 UniApp 跨端开发的实践经验:

  • 业务分包:pkg-mall / pkg-order / pkg-live / pkg-coupon 按功能域分包,满足小程序 2MB 主包限制
  • nvue 原生渲染:直播详情页使用 nvue,视频播放和弹幕渲染性能接近原生
  • 条件编译#ifdef H5 / #ifndef H5 处理平台差异(如 TCPlayer vs 原生 video)
  • 组件化设计:20+ 组件按功能分组,弹幕组件实现去重、自动滚动、智能渲染
  • Hooks 封装:useLiveRoom 封装直播间切换、群管理、播放器懒加载等逻辑

下一篇是本系列的收官之作,我们将深入会员激励体系的设计。


📦 久滴直播电商平台 是一个基于 Spring Boot 3 + Vue3 + UniApp 的全栈开源直播电商解决方案。

🔗 GitHub:https://github.com/jiudi-dev/live-mall-community(Community 版)

如果觉得本文对你有帮助,欢迎 Star ⭐ 支持!

Logo

一站式 AI 云服务平台

更多推荐