// plugins/smart-flexible.client.js class ResponsiveAdapter { constructor() { this.isMobile = this.checkMobile() this.init() } checkMobile() { const ua = navigator.userAgent.toLowerCase() const mobileKeywords = [ 'iphone', 'ipod', 'android.*mobile', 'windows.*phone', 'blackberry.*mobile', 'mobile', 'tablet' ] const isMobileUA = mobileKeywords.some(keyword => new RegExp(keyword).test(ua) ) const screenWidth = window.innerWidth const isSmallScreen = screenWidth <= 768 return isMobileUA || isSmallScreen } init() { const docEl = document.documentElement if (this.isMobile) { // 移动端逻辑 this.initMobile(docEl) } else { // PC 端逻辑 this.initPC(docEl) } // 添加设备标识类 this.addDeviceClass(docEl) // 监听窗口变化 window.addEventListener('resize', () => { this.handleResize(docEl) }) } initMobile(docEl) { const dpr = window.devicePixelRatio || 1 // 设置 viewport meta this.setViewport(dpr) // 设置 rem const setRem = () => { const rem = docEl.clientWidth / 10 docEl.style.fontSize = rem + 'px' } setRem() window.addEventListener('resize', setRem) // 存储方法供外部调用 this.setRem = setRem } initPC(docEl) { // PC 端使用响应式 rem const setPCRem = () => { const width = docEl.clientWidth // 响应式断点 let fontSize if (width >= 1920) { fontSize = 192 // 1920/10 } else if (width >= 1600) { fontSize = 160 // 1600/10 } else if (width >= 1440) { fontSize = 144 // 1440/10 } else if (width >= 1366) { fontSize = 136.6 // 1366/10 } else if (width >= 1200) { fontSize = 120 // 1200/10 } else { fontSize = 100 // 小于1200时的基准 } docEl.style.fontSize = fontSize + 'px' } setPCRem() window.addEventListener('resize', setPCRem) this.setPCRem = setPCRem } setViewport(dpr) { let viewport = document.querySelector('meta[name="viewport"]') if (!viewport) { viewport = document.createElement('meta') viewport.name = 'viewport' document.head.appendChild(viewport) } if (this.isMobile) { viewport.content = `width=device-width, initial-scale=${1/dpr}, maximum-scale=${1/dpr}, minimum-scale=${1/dpr}, user-scalable=no` } else { viewport.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no' } } addDeviceClass(docEl) { docEl.classList.remove('is-pc', 'is-mobile') docEl.classList.add(this.isMobile ? 'is-mobile' : 'is-pc') } handleResize(docEl) { const wasMobile = this.isMobile this.isMobile = this.checkMobile() if (wasMobile !== this.isMobile) { // 设备类型发生变化 this.addDeviceClass(docEl) if (this.isMobile) { this.initMobile(docEl) } else { this.initPC(docEl) } } else { // 同设备类型,只更新 rem if (this.isMobile && this.setRem) { this.setRem() } else if (!this.isMobile && this.setPCRem) { this.setPCRem() } } } } // 初始化 export default defineNuxtPlugin(() => { if (process.client) { new ResponsiveAdapter() } })