扒一扒 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 设计要简单 :用户只关心 designWidthdesignHeight,不要把复杂的计算抛给用户。
  2. 善用现代 APIResizeObserverresize 事件更好用。
  3. 组件化思维 :通过 FitContainer 把"定位计算"封装起来,业务代码里就全是干净的 px 值了。

总结

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

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

相关推荐
syty20201 分钟前
RedisTemplate方法汇总
前端·bootstrap·html
懒大王、4 分钟前
Vue dcm文件预览
前端·javascript·vue.js·dcm·cornerstone.js
C_心欲无痕7 分钟前
Docker 本地部署 SSR 前端项目实战指南
前端·docker·容器
梵得儿SHI17 分钟前
Vue 高级特性:组件高级用法(动态组件、异步组件、组件缓存 keep-alive)
前端·javascript·vue.js·keep-alive·异步组件·动态组件·vue组件高级特性
EndingCoder18 分钟前
泛型类和高级用法
linux·运维·前端·ubuntu·typescript
ℋᙚᵐⁱᒻᵉ鲸落24 分钟前
【Vue3】Element Plus 表单显示自定义校验错误
前端·javascript·vue.js
程序员小寒25 分钟前
聊一聊 CommonJS 和 ES6 Module
前端·ecmascript·es6
Java后端的Ai之路26 分钟前
【AI应用开发工程师】-Gemini写前端的一个坑
前端·人工智能·gemini·ai应用开发工程师
亿元程序员26 分钟前
最近很火的一个拼图游戏,老板让我用Cocos3.8做一个...
前端
m0_7482500327 分钟前
C++ Web 编程
开发语言·前端·c++