一个链接,两种命运

你在给某连锁健身房做「会员扫码签到」系统。

需求很明确:

  • 前台贴一张二维码,教练和会员都扫它;
  • 教练用 PC 后台管理,要打开 Web 管理系统(React);
  • 会员用手机扫码,要跳转 H5 轻应用(Vue);

结果第一版上线,会员扫完直接进了后台首页,一脸懵:"这表格是干啥的?"

你立刻意识到:同一个链接,必须智能分流


解决方案:三层识别 + 渐进式加载

1. 表面用法:用 User-Agent 做第一道筛子

js 复制代码
// router.js
const PC_UA = /Windows|Macintosh|Linux/;
const MOBILE_UA = /Android|iPhone|iPad|iPod/;

function getDeviceType() {
  const ua = navigator.userAgent;
  if (PC_UA.test(ua)) return 'pc';
  if (MOBILE_UA.test(ua)) return 'mobile';
  // 🔍 降级:看屏幕宽度
  return window.innerWidth < 768 ? 'mobile' : 'pc';
}
js 复制代码
// entry.js
async function main() {
  const type = getDeviceType();
  if (type === 'pc') {
    await import('./web-app.js');      // 🔍 动态加载 PC 版
  } else {
    location.href = 'https://m.corp.com/app'; // 🔍 跳 H5
  }
}
main();

关键点:

  • PC 端直接加载 SPA,不跳转,体验无缝;
  • 手机端跳转到独立 H5 域名,便于独立迭代和 SEO。

2. 底层机制:为什么不能只靠 UA?

识别方式 准确率 风险 适用场景
User-Agent 90% 可伪造,部分平板 UA 模糊 快速分流
屏幕尺寸 85% 折叠屏、横屏 iPad 易误判 降级兜底
触摸支持 95% maxTouchPoints > 1 更准 辅助判断

最终用 组合判断 提升准确率:

js 复制代码
function isMobile() {
  const ua = navigator.userAgent;
  if (/Android|iPhone/.test(ua)) return true;
  if (/iPad|Macintosh/.test(ua) && 'ontouchend' in document) return true; // 🔍 iPadOS
  return window.innerWidth <= 768 && navigator.maxTouchPoints > 1;
}

3. 设计哲学:把"分流"做成中间层服务

与其在每个项目里重复写判断逻辑,不如抽成一个 轻量级网关层

js 复制代码
// gateway.js (Node.js)
app.get('/entry', (req, res) => {
  const { userAgent, 'x-forwarded-for': ip } = req.headers;
  const isMobile = /Android|iPhone|Mobile/.test(userAgent);
  
  if (isMobile) {
    res.redirect('https://m.corp.com/app?from=' + ip); // 🔍 带来源信息
  } else {
    res.sendFile(path.join(__dirname, 'web/index.html')); // 🔍 直接吐 PC 页面
  }
});

这样前端只维护一个入口页,逻辑全在服务端,便于灰度、埋点、拦截爬虫


应用扩展:可复用的配置片段

1. 静态页分流模板(零后端依赖)

html 复制代码
<!-- index.html -->
<script>
  (function() {
    const mobileRegex = /Android|iPhone|iPad|iPod|Mobile/;
    if (mobileRegex.test(navigator.userAgent)) {
      location.replace('https://m.corp.com/app');
    }
    // 否则继续加载 React/Vue 脚本
  })();
</script>

2. 环境适配说明

场景 注意点
微信内置浏览器 UA 含 MicroMessenger,但仍是 mobile,正常跳 H5
iPadOS 默认 UA 像 Mac,需检测 ontouchendmaxTouchPoints
PWA 安装后 window.matchMedia('(display-mode: standalone)') 可识别,但分流不依赖它

举一反三:3 个变体场景

  1. App 内嵌 H5 智能跳转
    在 UA 里加自定义字段 MyApp/1.0,识别到后跳 myapp://page/signin 唤起原生页。
  2. PC 平板混合设备(Surface)
    先按 PC 加载,但监听页面 touchstart 事件,3 秒内有触摸则提示:"检测到触屏,是否切换平板模式?"
  3. AB 测试分流
    在 gateway 层加逻辑:Math.random() < 0.1 的 mobile 用户强制看 PC 版,收集体验反馈。

小结

别让设备类型决定代码,而要让代码聪明地认识设备。

用 UA 做快筛,尺寸和触摸做兜底,服务端做管控,一个链接也能走出两条路。

相关推荐
Amodoro22 分钟前
nuxt更改页面渲染的html,去除自定义属性、
前端·html·nuxt3·nuxt2·nuxtjs
Wcowin30 分钟前
Mkdocs相关插件推荐(原创+合作)
前端·mkdocs
伍哥的传说1 小时前
CSS+JavaScript 禁用浏览器复制功能的几种方法
前端·javascript·css·vue.js·vue·css3·禁用浏览器复制
lichenyang4531 小时前
Axios封装以及添加拦截器
前端·javascript·react.js·typescript
Trust yourself2431 小时前
想把一个easyui的表格<th>改成下拉怎么做
前端·深度学习·easyui
三口吃掉你2 小时前
Web服务器(Tomcat、项目部署)
服务器·前端·tomcat
Trust yourself2432 小时前
在easyui中如何设置自带的弹窗,有输入框
前端·javascript·easyui
烛阴2 小时前
Tile Pattern
前端·webgl
前端工作日常2 小时前
前端基建的幸存者偏差
前端·vue.js·前端框架
Electrolux2 小时前
你敢信,不会点算法没准你赛尔号都玩不明白
前端·后端·算法