用 Quasar 框架高效构建跨平台前端应用实战经验分享

IT人庆晨 框架 阅读 1,862
赞 14 收藏
二维码
手机扫码查看
反馈

项目初期的技术选型

去年年底接手一个内部管理系统,需求是做一套同时支持桌面和移动端的后台界面。团队人少,工期紧,老板还要求“看起来专业点”。我一开始想用纯 Vue + Element Plus,但测试发现移动端体验太差,滚动卡顿、按钮太小,用户反馈一堆问题。后来翻了下 Quasar 的文档,发现它主打“一次开发,多端部署”,而且组件库对移动端做了深度优化,就决定试试。

用 Quasar 框架高效构建跨平台前端应用实战经验分享

其实之前没用过 Quasar,心里有点打鼓,但看它基于 Vue 3,生态也成熟,社区活跃度还行,就硬着头皮上了。事实证明,这个选择在基础体验上确实省了不少事——比如表单、表格、弹窗这些,开箱即用,适配手机和平板基本不用额外调样式。

最大的坑:性能问题

项目做到一半,突然发现列表页在低端安卓机上滚动特别卡,甚至偶尔白屏。一开始以为是数据量太大(一页 100 条),但用 Chrome DevTools 看,FPS 掉到 10 以下,明显是渲染问题。折腾了半天才发现,Quasar 的 QTable 在默认模式下会把所有行都渲染出来,哪怕你只看到 10 行。

查了官方文档,发现它支持虚拟滚动(virtual scroll),但配置有点绕。我一开始直接套用示例代码,结果滚动时内容错乱,行高不对。后来才意识到,虚拟滚动要求每一行的高度必须固定,而我们的表格里有动态内容(比如备注字段可能换行),导致实际高度不一致。

没办法,只能妥协:限制备注字段最多显示两行,超出部分用 text-overflow: ellipsis 截断。这样虽然牺牲了一点信息完整性,但性能立马稳了。附上最终配置:

<q-table
  virtual-scroll
  :virtual-scroll-item-size="60"
  :rows="tableData"
  :columns="columns"
  row-key="id"
/>

注意这里 virtual-scroll-item-size 必须和 CSS 中设定的行高一致,否则会出现空白或重叠。我踩过好几次坑,每次改完样式忘了同步这个值,上线后又被测试提 bug。

又踩坑了,touchmove 滚动失效

另一个头疼的问题是在 iOS 上,某些页面内嵌的滚动区域(比如弹窗里的长表单)无法正常滑动。手指一划,整个页面跟着动,而不是弹窗内容滚动。查了好久,发现是 Quasar 的全局事件监听和我们自定义的 touch 逻辑冲突了。

具体来说,我们在某个组件里加了 @touchmove.prevent 来阻止默认行为,结果把 Quasar 内部用于识别滚动容器的逻辑也干掉了。解决方法是在需要滚动的容器上显式加上 scroll-target 属性,并且确保没有其他地方拦截了 touch 事件。

后来调整了方案,把所有自定义手势逻辑都移到了 passive: true 的监听器里,避免调用 preventDefault()。关键代码如下:

// 错误做法
el.addEventListener('touchmove', (e) => {
  e.preventDefault(); // 别这么干!
});

// 正确做法
el.addEventListener('touchmove', handler, { passive: true });

这个改动不大,但影响范围广,改完后所有弹窗内的滚动都恢复正常了。不过现在想想,其实更稳妥的做法是完全依赖 Quasar 提供的滚动组件(比如 QScrollArea),而不是自己处理 touch 事件——但当时时间紧,只能局部修复。

核心代码就这几行

项目里最让我满意的部分是主题切换功能。Quasar 支持动态主题,但文档写得比较散。我最后用 Vuex 管理主题状态,配合 Quasar 的 setBrand API 实现一键切换。核心逻辑其实就几行:

// store/modules/theme.js
import { setBrand } from 'quasar';

const state = {
  darkMode: false
};

const mutations = {
  TOGGLE_DARK_MODE(state) {
    state.darkMode = !state.darkMode;
    const mode = state.darkMode ? 'dark' : 'light';
    
    // 动态切换主色和背景
    setBrand('primary', mode === 'dark' ? '#88c7ff' : '#1976d2');
    setBrand('background', mode === 'dark' ? '#121212' : '#ffffff');
  }
};

然后在 App.vue 里监听状态变化:

watch: {
  '$store.state.theme.darkMode'(newVal) {
    this.$q.dark.set(newVal);
  }
}

亲测有效,切换流畅,连动画过渡都自带。不过有个小问题一直没解决:首次加载时如果系统是深色模式,页面会先闪一下白色再变黑。理论上可以通过 SSR 或 localStorage 预判,但项目没上 SSR,最后就加了个 loading 遮罩糊弄过去了——反正只闪 100ms,用户基本无感。

回顾与反思

整体来看,Quasar 在这个项目里表现不错。开发效率高,组件一致性好,移动端适配省心。特别是它的 CLI 工具,打包 PWA、生成 Cordova 项目都很方便,虽然我们最后只用了 Web 版。

但也有几个地方可以优化:

  • Bundle 体积偏大:即使按需引入,基础包还是比纯 Vue 大不少。下次如果只是简单后台,可能还是选轻量级方案。
  • 文档示例不够实战:很多高级用法(比如虚拟滚动 + 动态高度)得自己摸索,社区问答质量参差不齐。
  • TypeScript 支持一般:类型定义有些滞后,经常要自己加 @ts-ignore

不过话说回来,在人手不足、多端需求明确的场景下,Quasar 依然是个靠谱的选择。至少比自己从零搭一套响应式系统强多了。

以上是我踩坑后的总结,希望对你有帮助。如果你也在用 Quasar,遇到类似问题或者有更好的解法,欢迎评论区交流——尤其是那个深色模式闪白的问题,至今耿耿于怀。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论