跳到主要内容

响应式方案

UI 层适配

常见的响应式方案

Media query

css 中使用

/* css中使用  */
@media (max-width: 1600px) {
width: 50%;
my_image {
width: 640px;
}
}
@media (max-width: 1300px) {
display: none;
}

CSS3 中的增加了更多的媒体查询,就像 if 条件表达式一样,我们可以设置不同类型的媒体条件,并根据对应的条件,给相应符合条件的媒体调用相对应的样式表 使用@Media 查询,可以针对不同的媒体类型定义不同的样式,如: 当视口在 375px - 600px 之间,设置特定字体大小 18px

@media screen (min-width: 375px) and (max-width: 600px) {
body {
font-size: 18px;
}
}

媒体查询,可以通过给不同分辨率的设备编写不同的样式来实现响应式的布局,比如我们为不同分辨率的屏幕,设置不同的背景图片 比如给小屏幕手机设置@2x 图,为大屏幕手机设置@3x 图,通过媒体查询就能很方便的实现

js 中使用

// js中使用,创建mediaquery对象,然后监听onChange
const mediaQuery = window.matchMedia("(max-width: 1000px)");
mediaQuery.onChange = (e) => {
if (e.matches) {
// 达到临界点时给用户提示
当前小于1000px;
} else {
当前大于1000px;
}
};

html5 img 标签属性(仅限图片响应式)

默认 960w 如果浏览器标识 2x 像素比,则会用 img-640w.jpg

<img srcset="img-320w.jpg,img-640w.jpg 2x" src="img-960w.jpg" alt="img" />
<!-- x表示图像的设备像素比 -->

viewport 适配

根据设计稿标准(750px 宽度)开发页面,

写完后拿到屏幕尺寸,手动加上 meta 标签,浏览器按 meta 标签使页面及元素自动等比缩小,适配 375 宽度的屏幕 通过在 head 里设置如下代码实现

<meta name="viewport" content="width=750,initial-scale=0.5" /> initial-scale =
屏幕的宽度 / 设计稿的宽度 所以要手动计算
<head>
<script>
const WIDTH = 750
const mobileAdapter = () => {
// 主要在于拿到screen.width
let scale = screen.width / WIDTH
let content = `width=${WIDTH}, initial-scale=${scale}, maximum-scale=${scale}, minimum-scale=${scale}`
// 可以选到meta标签
let meta = document.querySelector('meta[name=viewport]')
if (!meta) {
meta = document.createElement('meta')
meta.setAttribute('name', 'viewport')
document.head.appendChild(meta)
}
meta.setAttribute('content',content)
}
mobileAdapter()
window.onorientationchange = mobileAdapter //监听到屏幕翻转时再次执行
</script>
</head>

缺点就是边线问题,不同尺寸下,边线的粗细是不一样的(等比缩放后),全部元素都是等比缩放,实际显示效果可能不太好

vw/vh

解决边线问题,需要等比缩放的使用 vw,否则使用 px

  1. 比如页面元素字体标注的大小是 32px,换成 vw 为 (100/750)*32 vw
  2. 对于需要等比缩放的元素,CSSvw
  3. 对于不需要缩放的元素,比如边框阴影,使用固定单位 px
<head>
<meta
name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"
/>
<script>
//设计稿width!!!
const WIDTH = 750;
//:root { --width: 0.133333 } 1像素等于多少 vw
// 关于换算,为了开发方便,利用自定义属性,CSS变量
document.documentElement.style.setProperty("--width", 100 / WIDTH);
</script>
</head>
// 28 vw = 28/100 * 屏幕实际 // 100/设计稿 / 最终变为28px*
实际/设计稿,完成相应变化 // header { font-size: calc(28vw * var(--width)) }

rem

rem 适配

  1. 开发者拿到设计稿(假设设计稿尺寸为 750px,设计稿的元素标是基于此宽度标注)
  2. 开始开发,对设计稿的标注进行转换
  3. 对于需要等比缩放的元素,CSS 使用转换后的单位
  4. 对于不需要缩放的元素,比如边框阴影,使用固定单位 px 假设设计稿的某个字体大小是 40px, 手机屏幕上的字体大小应为 420/750*40 = 22.4px (体验好),换算成 rem(相对于 html 根节点,假设 html 的 font-size = 100px,)则这个字体大小为 0.224 rem 写样式时,对应的字体设置为 0.224 rem 即可,其他元素尺寸也做换算...

设计稿的标注 是 40px,写页面时还得去做计算,很麻烦(全部都要计算) 能不能规定一下,看到 40px ,就应该写 40/100 = 0.4 rem,这样看到就知道写多少了(不用计算), 手动设置根标签字体大小即可

<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
<script>
const WIDTH = 750 //设计稿尺寸
const setView = () => {
document.documentElement.style.fontSize = (100 * screen.width / WIDTH) + 'px'
}
window.onorientationchange = setView
setView()
</script>
</head>

grid/flex

百分比

要求:图片宽度不能小于 184px, 尽量占满一行,水平和上下间距固定

display: grid;
grid-gap: 24px 16px;
grid-template-columns:
repeat(auto-fill, minmax(184px, 1fr))
auto-fill 尽可能多的列充满着一行,如果列不够不会扩展
auto-fit 列不够,会把每一列强制放大占满一行;

特殊设备适配

建议抽离出通用 hooks 可以放在高阶组件里使用,然后原先的组件传进高阶组件,如果应该展示返回 children,否则返回 null

服务层适配

当应用在不同端或尺寸屏幕上有很大差异时,仅用前文的 UI 层适配就无法满足要求了,在同一个项目需要进行大量判断,复杂度和维护难度大大提升;建议把项目分割成多个项目,分别部署服务 解决方案:

  • 在 monorepo 中初始化两个不同的 package 分别用于 PC 代码和 Mobile 代码
  • 抽取通用的逻辑 utils (翻译逻辑,数据获取逻辑)
  • 将项目部署在不同的服务上
  • 在 TLB 层进行配置,请求时获取设备信息,将不同的用户分流到不同服务