【Vue3】如何一个项目实现PC/移动端的多端适配
写在前面:
什么是多端适配?
前端的多端适配是指在开发前端网页或应用程序时,通过编写不同的布局和样式代码,使得同一个项目能够适应不同的终端设备,如PC端和移动端,以提供更好的用户体验。 由于PC端和移动端的屏幕尺寸、分辨率、交互方式等存在差异,为了使网页或应用程序在不同设备上都能正常显示和使用,需要进行多端适配。
效果如下:
实现步骤:
1.判断客户端是否为移动端设备
首先,创建一个工具类js,用于存放相关判断函数
创建isWap
以及isWapPage
函数,用于检测当前设备是否为移动端设备
1.函数 isWap
定义一个变量 userAgentInfo
,它保存了浏览器的用户代理信息。然后,定义一个包含各种移动设备名称的数组 Agents
。变量 flag
被初始化为 true
,用于标记当前设备是否为移动设备。
接下来,通过遍历 Agents
数组,检查用户代理信息中是否包含其中任何一个移动设备的名称。如果包含,说明当前设备是移动设备,将 flag
设置为 false
并跳出循环。
在 flag
为 true
的情况下,通过获取页面可视区域的宽度,判断当前设备是否为移动设备。如果宽度小于 840 像素,则被判定为手机设备,将 flag
设置为 false
。
最后返回 !flag
,即返回当前设备是否为移动设备的布尔值。
2.函数 isWapPage
用于检测当前页面是否是移动端页面。首先创建一个空数组 routerNames
,然后定义了一个递归函数 getAllRouterNames
,用于遍历 routers
数组并将路由名称存储在 routerNames
中。
接着通过 window.location.href
获取当前页面的 URL,并使用 split('#')[1]
获取 URL 中的路径部分。然后,使用 router.resolve(path)
解析路径对应的路由信息,将结果保存在 curRoute
变量中。
最后判断 isWap()
是否为 true
,以及当前路由名称是否包含 -wap
或者在 routerNames
中是否存在当前路由名称加上 -wap
的形式,来确定当前页面是否是移动端页面。如果是,则返回 true
,否则返回 false
。
代码如下:
export const isWap = () => {
var userAgentInfo = navigator.userAgent
var Agents = [
'Android',
'iPhone',
'SymbianOS',
'Windows Phone',
'iPad',
'iPod'
]
var flag = true
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false
break
}
}
if (flag) {
let width =
document.documentElement.clientWidth || document.body.clientWidth
if (width < 840) {
//小于840px的屏幕,判定为手机
flag = false
}
}
return !flag
}
/** 当前url是否对应的wap页面 */
export const isWapPage = () => {
const routerNames = []
const getAllRouterNames = array => {
array.forEach(element => {
routerNames.push(element.name)
if (element.children?.length) {
getAllRouterNames(element.children)
}
})
}
getAllRouterNames(routers)
const path = window.location.href.split('#')[1]
const curRoute = router.resolve(path)
if (
isWap() &&
((curRoute.name.indexOf('-wap') < 0 &&
routerNames.includes(curRoute.name + '-wap')) ||
curRoute.name.indexOf('-wap') >= 0)
) {
return true
} else {
return false
}
}
2.判断是否为刘海屏并对iphone进行刘海屏优化
创建几个判断函数:
-
1.函数
judgeClient
用于判断客户端类型,即判断当前设备是 Android、iOS 还是 PC。首先获取浏览器的用户代理信息,并根据用户代理信息中是否包含关键字 "Android" 或 "Adr" 来判断是否是 Android 终端。然后使用正则表达式匹配用户代理信息,判断是否是 iOS 终端。最后,根据判断结果返回相应的客户端类型。 -
2.函数
isiPhoneX
用于判断当前设备是否是刘海屏(iPhone X 及其后续型号)。它通过调用judgeClient
函数获取客户端类型,并根据一系列判断条件来确定是否是刘海屏设备。判断条件涉及设备的屏幕高度和宽度与特定型号的对比。 -
3.函数
safeBottomHeight
返回一个安全区域底部高度,用于适配刘海屏设备。如果当前设备是刘海屏(通过调用isiPhoneX
函数判断),则返回 44;否则返回 0。 -
4.函数
safeTopHeight
返回一个安全区域顶部高度,用于适配刘海屏设备。如果当前设备是刘海屏(通过调用isiPhoneX
函数判断),则返回 22;否则返回 0。 -
5.函数
statusBarHeight
返回一个状态栏高度,根据客户端类型和是否是刘海屏来确定。如果客户端类型是 iOS 并且是刘海屏设备(通过调用judgeClient
和isiPhoneX
函数判断),则返回 44;否则返回 20。
通过以上配置即可实现刘海屏iphone移动端页面适配,如果只适配移动端不专门进行优化这一步可以忽略 代码如下:
/** 判断客户端:Android,IOS,PC */
export const judgeClient = () => {
let u = navigator.userAgent
let isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1 //判断是否是 android终端
let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) //判断是否是 iOS终端
if (isAndroid) {
return 'Android'
} else if (isIOS) {
return 'IOS'
} else {
return 'PC'
}
}
/** 是否是刘海屏 */
export const isiPhoneX = () => {
return (
(judgeClient() === 'IOS' &&
((D_HEIGHT === X_HEIGHT && D_WIDTH === X_WIDTH) ||
(D_HEIGHT === X_WIDTH && D_WIDTH === X_HEIGHT))) ||
(D_HEIGHT === XSMAX_HEIGHT && D_WIDTH === XSMAX_WIDTH) ||
(D_HEIGHT === XSMAX_WIDTH && D_WIDTH === XSMAX_HEIGHT) ||
(D_HEIGHT === p12_HEIGHT && D_WIDTH === p12_WIDTH) ||
(D_HEIGHT === p12_WIDTH && D_WIDTH === p12_HEIGHT) ||
(D_HEIGHT === p12_MAX_HEIGHT && D_WIDTH === p12_MAX_WIDTH) ||
(D_HEIGHT === p12_MAX_WIDTH && D_WIDTH === p12_MAX_HEIGHT)
)
}
export const safeBottomHeight = () => {
return isiPhoneX() ? 44 : 0
}
export const safeTopHeight = () => {
return isiPhoneX() ? 22 : 0
}
export const statusBarHeight = () => {
return judgeClient() === 'IOS' ? (isiPhoneX() ? 44 : 20) : 0
}
3.全局引入isWapPage
在main.js
中添加以下代码:
import { isWapPage } from './utils/index'
import './wap'
const wap = isWapPage()
if (wap) {
app = createApp(WapApp)
app.use(Vant)
} else {
app = createApp(App)
app.use(Antd)
}
4.配置全局前置路由守卫,不同设备将打开不同的页面
1.在路由index.js中,创建三个判断函数用于判断是否需要跳转到移动端页面或 PC 端页面。
函数 existWapPage
接收一个路由名称 routeName
,它的作用是检查是否存在对应的移动端页面。首先创建一个空数组 routerNames
,然后定义了一个递归函数 getAllRouterNames
,用于遍历 routers
数组并将路由名称存储在 routerNames
中。最后,通过判断 routerNames
是否包含 routeName + '-wap'
,来确定是否存在对应的移动端页面,并返回相应的布尔值。
函数 needJumpToWap
接收一个路由名称 routeName
,它判断是否需要跳转到移动端页面。首先通过调用 isWap()
函数判断当前设备是否为移动设备。如果是移动设备,并且 routeName
中不包含 -wap
,并且存在对应的移动端页面(通过调用 existWapPage(routeName)
函数判断),则返回 true
,否则返回 false
。
函数 needJumpToPC
接收一个路由名称 routeName
,它判断是否需要跳转到 PC 端页面。首先通过调用 isWap()
函数判断当前设备是否为移动设备。如果不是移动设备,并且 routeName
中包含 -wap
,则返回 true
,否则返回 false
。
这些函数的目的是根据当前设备和路由名称,判断是否需要进行页面跳转,以适配不同的设备类型。
const existWapPage = routeName => {
const routerNames = []
const getAllRouterNames = array => {
array.forEach(element => {
routerNames.push(element.name)
if (element.children?.length) {
getAllRouterNames(element.children)
}
})
}
getAllRouterNames(routers)
return routerNames.includes(routeName + '-wap')
}
const needJumpToWap = routeName => {
if (isWap() && routeName.indexOf('-wap') < 0 && existWapPage(routeName)) {
return true
} else {
return false
}
}
const needJumpToPC = routeName => {
if (!isWap() && routeName.indexOf('-wap') >= 0) {
return true
} else {
return false
}
}
2.配置全局前置路由守卫:
代码如下:
在这段代码中,通过这个钩子函数来处理不同设备之间的页面跳转逻辑。
- 首先,执行了一些初始化操作,然后进行设备判断和处理wap跳转PC、PC跳转wap的逻辑。
- 如果当前设备不是移动设备,并且路由名为 "approval-dap" 或 "approval-dap-wap",则根据不同的条件进行页面跳转。
- 如果当前设备是移动设备,并且路由参数中的
appId
为 "2",applyType
为 "21",则进行相应的页面跳转。 - 如果满足
needJumpToWap(to.name)
的条件,表示需要跳转至移动端页面,则执行相应的跳转逻辑。 - 如果满足
needJumpToPC(to.name)
的条件,表示需要跳转至PC端页面,则执行相应的跳转逻辑。 - 如果以上条件都不满足,则执行其他逻辑,并进行下一步路由导航。
5.编写移动端/PC端两套代码
至此,已经完成了一个项对PC/移动端进行多端适配,并显示两套不同的页面,只需要将pc端以及移动端页面分开存放,进行路由跳转即可。
转载自:https://juejin.cn/post/7277224541637525544