扒一扒 Vue3 大屏适配插件 vfit 的源码:原来这么简单?

前几天用了 vfit 做大屏适配,感觉挺好用的。 作为一个有追求的前端(其实是闲得蛋疼),我忍不住扒了一下它的源码。 结果发现... 核心代码居然不到 50 行? 🤯

今天就带大家深入浅出地拆解一下这个库,看看它是如何优雅地解决大屏适配问题的。

🎯 核心原理:Scale 方案

大屏适配的核心流派无非就那几种:

  1. REM / VW:修改基准值,所有单位都要改,侵入性强。
  2. Scale :CSS transform: scale(),简单粗暴,不改变布局。

vfit 采用的是 Scale 方案。 它的思路非常清晰:

计算 当前屏幕宽高 / 设计稿宽高 = 缩放比例,然后应用到根容器上。

🔍 源码拆解

1. 监听屏幕变化 (ResizeObserver)

在 src/scale.ts 里,它没有使用传统的 window.onresize,而是用了更现代、性能更好的 ResizeObserver。

typescript 复制代码
// src/scale.ts (简化版)
export function observeScale(target, designHeight, onScale) {
  const observer = new ResizeObserver((entries) => {
    for (const entry of entries) {
      const { width, height } = entry.contentRect
      // ... 计算 scale 逻辑
      onScale(scaleVal)
    }
  })
  observer.observe(target)
}

为什么用 ResizeObserver? 因为它能监听任意元素的大小变化,而不仅仅是 window。这意味着你可以把大屏嵌入到一个 div 里(比如后台管理系统的某个 dashboard 页签),它依然能正常缩放!

2. 三种缩放模式的算法

vfit 支持 width | height | auto 三种模式。 看看它是怎么算的:

typescript 复制代码
// src/scale.ts
if (scaleMode === 'height') {
  // 1. 只要高度撑满,宽度按比例缩放(适合定高宽屏)
  scaleVal = rectHeight / designHeight
} else if (scaleMode === 'width') {
  // 2. 只要宽度撑满,高度按比例缩放(适合定宽长页面)
  scaleVal = rectWidth / designWidth
} else {
  // 3. auto 模式 (默认):保持宽高比,全部显示 (Contain)
  const designRatio = designWidth / designHeight
  // 如果当前屏幕更宽(带鱼屏),就以高度为基准
  // 如果当前屏幕更窄(手机),就以宽度为基准
  if (rectWidth / rectHeight < designRatio) {
    scaleVal = rectWidth / designWidth
  } else {
    scaleVal = rectHeight / designHeight
  }
}

这段逻辑非常经典,保证了内容永远不会被裁剪,同时也保持了设计稿的比例。

3. 神奇的 FitContainer

大家用 scale 方案最头疼的是什么? 是定位! 😫 一旦缩放了,原来的 top: 100px 可能就不是视觉上的 100px 了,而且居中后的偏移量也很难算。

vfit 的 FitContainer.vue 组件用了一个很巧妙的思路解决这个问题:

typescript 复制代码
// src/components/FitContainer.vue

// 监听 scale 和 props 变化
watch([() => props.scale, fitScale], () => {
  const s = fitScale.value
  
  // 对于 left 和 top,乘以缩放比例 s
  // 这样就能让元素相对于原点进行位移
  if (key === 'left' || key === 'top') {
    position[key] = val * s + 'px'
  }
  
  // 对于 right 和 bottom,不乘!
  // 这样元素就会死死贴住容器边缘
  else {
    position[key] = val + 'px'
  }
})

这里有个细节设计得很赞:

  • top / left:参与缩放。这意味着你给的坐标是相对于"设计稿左上角"的。
  • right / bottom:不参与缩放。这意味着你给的坐标是相对于"屏幕边缘"的。

这解决了大屏开发的一个痛点:中间内容要还原设计稿,但边缘菜单要贴边。

💡 我们可以学到什么?

  1. API 设计要简单 :用户只关心 designWidth 和 designHeight,不要把复杂的计算抛给用户。
  2. 善用现代 API :ResizeObserver 比 resize 事件更好用。
  3. 组件化思维 :通过 FitContainer 把"定位计算"封装起来,业务代码里就全是干净的 px 值了。

总结

vfit 的源码虽然简单,但确实切中了痛点。 有时候造轮子不一定要多高深的技术,能优雅地解决一个小问题,就是一个好轮子。

推荐大家去读读它的源码,就几个文件,半小时就能看完。 👉 GitHub: v-plugin/vfit

相关推荐
m0_敲代码的彭于晏1682 小时前
Vercel 前端部署平台深度评测
前端
怕浪猫3 小时前
外包和大厂的前端代码,差在凌晨三点
前端·面试·github
m0_敲代码的彭于晏1684 小时前
Vercel 前端部署与全栈开发实战指南
前端·状态模式
徐小夕4 小时前
花了3个月,我们做了一款 AI 版的“飞书文档”
前端·算法·github
贾伟康4 小时前
【化学实验室|17】HarmonyOS ArkTS 亮暗色与视觉令牌实战:集中颜色、间距和交互状态避免页面割裂
前端·移动开发·harmonyos·arkts·arkui
Csvn5 小时前
SSR/SSG/ISR(上):峡谷与渲染策略的时间预算
前端
Csvn5 小时前
SSR/SSG/ISR(下):可交互性、新鲜度与回源账
前端
Elcker7 小时前
YnuoAgent(依诺):一个 npm 包,跑起属于自己的 AI 研发平台
前端·人工智能·npm
计算机魔术师8 小时前
发现2天,修复2个月:AI挖穿PHP后,卡兹克讲透攻防时间差
前端
风骏时光牛马8 小时前
测试标题001
前端