Vue3多端项目实战——开发一个多端音乐 APP我踩了很多坑!

语言: CN / TW / HK

项目背景

先来聊聊为啥要搞这个玩意?有以下几个方面的原因吧:

  1. Vue3 已经发布很久了,公司还没有积极拥抱 Vue3,笔者还停留在看Vue3文档阶段(看文档的效果还是没有以实际项目推动来得快,毕竟看完刷刷短视频就忘了🌝),所以想做个个人项目积累经验。
  2. 女朋友吐槽,QQ 音乐、网易云音乐广告很多,Apple Music 个性推荐又不太懂我的个性。
  3. 笔者毕业之后一直在搞 PC 端的项目,没有移动端项目经验。

基于上述三点,这个项目就正式立项了。

技术选型

  • 技术栈没得说了,拥抱 Vite、Vue3
  • 没有多端经验,那就用 uni 吧,我倒是要看看是不是像吹得那么牛逼
  • 全局状态管理没的说 pinia
  • 路由就不需要了,毕竟小项目嘛,逻辑不太复杂,页面也不多,就不用 VueRouter 了,整个动态组件就 OK
  • i18n 也不需要了,项目简单,用 pinia 也能玩
  • css 扩展——sass, 抽离 css 变量,维护更方便
  • UI 组件库就不用了,uni 内置组价够用,别的就自己封装吧
  • 图标 iconfont 找了一套字体图标
  • 图片素材也是 iconfont 找的
  • logo 来自 标小智, 输入关键字会生成很多可选的 logo,然后需要付费下载,付费是不存在的!直接给水印去掉,再利用 Chrome 的 screenshot 拿到图片(清晰度不好,再找个网址修复下,哈哈)
  • UI 方面,我直接抄了 Apple Music 和 网易云音乐 的作业😄

最重要的——音乐来源

音源来自开源项目NeteaseCloudMusicApi,网易云音乐的音源。没踩到坑,文档非常给力,唯一的不足就是 查询我喜欢的音乐接口 不支持分页查,一次性就全搞回来了。

封装组价梳理

在项目中,我封装了很多基础组件 和 业务组件。

基础组件

| 组件 | 组件用处 | | --- | --- | | NoData | 无数据组件 | | NoLogin | 未登录组件 | | Message | 提示消息 | | Loading | 数据加载中组件(h5是指令,小程序不支持指令) | | LazyLoader | 图片懒加载组件 | | PageFrame | 页面容器组件,向下滚动标题吸顶,滑到底部加载更多数据 | | Process | 进度条组件 |

业务组件

| 组件 | 组件用处 | | --- | --- | | SongListItem | 歌曲条目组件 | | SongSheet | 歌曲组件 | | Category | 歌单列表 | | Search | 搜索组件,防抖处理 | | Player | 播放器组件 | | MySpace | 我的 | | Recommend | 推荐页 | | ...... | ...... |

亮点

  • 拥有 Apple Music 的颜值,玻璃拟态风格
  • 简约大气、无广告
  • 轻量 打包后体积一共 316kb,运行在 Chrome 后 memory 大概 7M 左右,加载的数据多了会大一些
  • KeepAlive 实现组件缓存
  • 异步加载组件 按需加载
  • 多端适配(wx 小程序、PC)
  • 网易云扫码登录(PC 很方便;小程序需要截图再扫码,没有找到对接微信登录的接口🙁)
  • 暗黑模式适配
  • 按照显示宽高请求图片,不让浏览器去缩放,提升性能

适配PC 和 手机 & 暗黑模式

为啥要说这个呢,我就是想表达一点,我们在开发时,将与主题相关的变量一定要抽出来,最后去做适配你会发现事半功倍的效果。

image.png

暗黑适配:没有使用 uni提供的方案,不喜欢配置,喜欢自己玩。 image.png

你没看错,就是那么几行!为啥要加 !important,因为 uni 默认给 style 加了 scope,导致优先级没有默认的样式高。

用 pinia 实现多语言

因为语言变量不多,我决定不用 i18n,将语言加载到全局状态管理即可: image.png

image.png

组合式函数抽离公共代码

请允许我说一声 Vue3 牛批! 项目组有两个地方都有 播放、暂停、下一曲、上一曲按钮,此时就该 组合式函数 上场优化代码了(一开始是复制的,最近才优化了😂)

image.png

使用:

image.png

部署相关

界面展示

推荐页

PC

image.png

wx小程序

我的

PC

image.png

wx小程序

歌单页

PC

image.png

wx小程序

歌曲列表

PC

image.png

wx小程序

播放器界面

PC

image.png

wx小程序

聊聊开发中遇到的坑

因为笔者没有移动端开发经验嘛,所以一路还是踩了不少坑,主要就是兼容性的问题,接下来我就详细和大家聊聊。一开始选择 uni 就是以为 uni 帮我们支持多端做了很多东西,能让我使用 h5 vue 的开发模式自动的就兼容了。所以想都没想,就开始用浏览器的移动设备模拟调试,一直都很顺利。

然后到了一个节点想着放到真机上跑一下,把流程跑通。用的苹果手机嘛,就想着能不能搞成App 跑一下啊,然后看 uni 的文档,需要一个苹果的 appid,所以就去注册了 Apple Developer Program,这破玩意要不就是登不上,要不就是注册不成功,对象的号都试了,后来看到还要收费,打扰了,破玩意,浪费时间!

还是选择 wx 小程序吧!这个比较容易,只不过跑起来后控制台报了一堆错误,这也不支持,那也不支持,样式也都不对!此时心中万马奔腾,靠!说好的 "一套代码,多端运行"?

image.png

经过我在 uni 文档的一番搜索浏览,我发现人家说的一套代码是需要这样的: image.png uni 文档中是这么说的:

uni-app 已将常用的组件、JS API 封装到框架中,开发者按照 uni-app 规范开发即可保证多平台兼容,大部分业务均可直接满足。

意思就是我用到的都是不常用的,所以需要自己写各端的实现才能跨端呗!好的我懂了,是我不会用 uni。于是我这就这样了: image.png 后续开发都是先实现任意一端,再将代码 cherry-pick 到另一个分支做一些选择性的合并。我也不知道我为啥要这么做,就当成强迫症吧!

好了接下来就聊聊具体的坑。

不支持指令

这个可能是移动端没有 dom, 而指令是操作 dom 的。所以全局 Loading 在 h5 是通过指令实现,小程序是封装成组件。

不支持 defineAsyncComponent

PC: image.png 小程序: image.png 不能使用 KeepAlive,那就只能缓存请求数据了。

IntersectionObserver问题

在实现下拉标题吸顶,下拉到底加载更多需要用到这玩意,PC没啥问题很好用, 我在这边文章中专门写了下:也许这是Vue3最简单的懒加载方案了(适用图片/组件)

小程序就很坑了: image.png 不能使用 script setup,因为在小程序端通过 uni.createIntersectionObserver 创建observer 实例,必须传入 this,否则监听无效(坑死个人🤢)

样式问题

小程序不支持挺多选择器

比如: css [class^=icon]{ }

css变量

css // pc :root { --global-bg: rgba(0, 0, 0, .9); --global-color: rgb(255, 255, 255); --bottom-bar-color: rgb(106, 106, 106); --bg: rgba(15, 15, 15, 0.6); --message-bg: rgba(15, 15, 15, 0.9); } // wx小程序 page { --global-bg: rgba(0, 0, 0, .9); --global-color: rgb(255, 255, 255); --bottom-bar-color: rgb(106, 106, 106); --bg: rgba(15, 15, 15, 0.6); --message-bg: rgba(15, 15, 15, 0.9); }

宽高继承问题

image.png

目前印象比较深刻的点就这些吧!

体验一下吧

体验地址: - PC:LVMusic - wx 小程序:

总结

通过本次实战,对移动端开发有了一个大概的认知: 1. uni 配置太多,有些坑文档没写清楚,上手学习成本还是不小,可能是因为我不看文档就开发,遇到问题才知道看文档。 2. 如果不熟悉的话,移动端开发会花很多时间在适配上 3. Vue3 组合式的语法真的很香 4. pinia 比 Vuex 更易用 5. 组合式函数抽离公用逻辑真的很牛批👍🏻 6. 等等......