【基础题】移动端点击延迟问题及解决方案
考察意图:是否了解移动端浏览器特性,能否解决实际体验问题。
标准回答框架:
- 问题现象:在iOS Safari中,点击事件延迟约300ms(因浏览器等待用户是否双击缩放);Android Chrome 56+已移除该延迟。
- 解决方案:
- ① 使用touchstart + preventDefault()模拟click(推荐)
- ② 引入FastClick库(已过时,不推荐新项目)
- ③ 设置meta viewport禁止缩放(⚠️影响可访问性)
- 代码示例:
// 方案①:原生 touchstart + preventDefault
document.addEventListener('touchstart', function(event) {
if (event.touches.length === 1) {
let touch = event.touches[0];
let target = touch.target;
// 检查是否为可点击元素
if (target.tagName.toLowerCase() !== 'input' &&
target.tagName.toLowerCase() !== 'textarea' &&
target.tagName.toLowerCase() !== 'select') {
event.preventDefault();
target.click();
}
}
}, { passive: false });
追问点:
① 为什么不能直接用click事件?
② 如何解决“延迟点击导致误触”问题?
③ touchstart触发后,click事件还会触发吗?
【进阶题】滚动穿透问题及三种解决方案
问题场景:在移动端弹出模态框后,用户滚动模态框时,底层页面同步滚动,影响体验。
标准回答框架:
- 原理:滚动事件未被阻止时,会冒泡至父容器(如body),触发底层滚动。
- 解决方案:
- ① CSS overflow:hidden(简单但有副作用)
- ② JavaScript阻止默认滚动(推荐)
- ③ 使用iscroll等滚动库(复杂场景)
- 代码示例:
// 方案②:动态控制body滚动
const modal = document.getElementById('modal');
let scrollPosition = 0;
function openModal() {
scrollPosition = window.scrollY;
document.body.style.position = 'fixed';
document.body.style.top = -scrollPosition + 'px';
document.body.style.width = '100%';
}
function closeModal() {
document.body.style.position = '';
document.body.style.top = '';
document.body.style.width = '';
window.scrollTo(0, scrollPosition);
}
modal.addEventListener('open', openModal);
modal.addEventListener('close', closeModal);
追问点:
① position:fixed在iOS 13+存在什么兼容性问题?
② 如何解决滚动到模态框顶部/底部后继续滚动导致的“回弹”?
③ 如何兼容Android 4.4以下浏览器?
【高阶题】PWA离线缓存策略设计(Service Worker实战)
考察意图:是否具备构建高可用移动Web应用的能力。
标准回答框架:
- 核心组件:Service Worker(SW) + Cache API + Navigation Preload
- 策略选择:根据资源类型动态选择缓存策略:
- 静态资源(CSS/JS)→ Cache First
- API数据 → Network First
- 图片 → Stale While Revalidate
- 代码示例:
// sw.js
const CACHE_NAME = 'mobile-app-v1';
const STATIC_ASSETS = [
'/index.html',
'/styles/main.css',
'/scripts/app.js'
];
self.addEventListener('install', (e) => {
e.waitUntil(
caches.open(CACHE_NAME)
.then(cache => cache.addAll(STATIC_ASSETS))
);
});
self.addEventListener('fetch', (e) => {
const { request } = e;
const url = new URL(request.url);
// 静态资源:缓存优先
if (url.origin === location.origin && STATIC_ASSETS.includes(url.pathname)) {
e.respondWith(
caches.match(request)
.then(cached => cached || fetch(request))
);
return;
}
// API请求:网络优先
if (url.pathname.startsWith('/api/')) {
e.respondWith(
fetch(request)
.then(network => {
caches.open(CACHE_NAME)
.then(cache => cache.put(request, network.clone()));
return network;
})
.catch(() => caches.match(request))
);
return;
}
});
追问点:
① 如何避免SW更新导致用户看到旧版页面?
② 如何处理SW中无法缓存的POST请求?
③ 如何与微信小程序Hybrid方案协同?