1.如何根据设备(电脑和手机)返回不同的页面?
使用请求头中的user-agent字段,通过useragent库处理,判断返回pc端或者移动端页面。 java可根据cn.hutool.http.useragent.UserAgent库,java库更加全面
// app.js
const express = require("express");
const useragent = require("useragent");
const app = express();
const port = 3000;
// 提供静态文件服务
app.use(express.static("public"));
// 定义主页路由
app.get("/", (req, res) => {
const agent = useragent.parse(req.headers["user-agent"]);
const isMobile = /iPhone|Android|Mobile/i.test(agent.device.family);
console.log(agent.device.family);
if (isMobile) {
res.sendFile(__dirname + "/public/mobile.html");
} else {
res.sendFile(__dirname + "/public/pc.html");
}
});
// 启动服务器
app.listen(port, () => {
console.log(`服务器正在运行在 http://localhost:${port}`);
});
2. 移动端响应式处理?
使用lib-flexible库,主要原理为: 页面加载完成后设置html标签(rem基于html计算)的字体大小,并在窗口大小改变时重新设置。
var doc = win.document;
var docEl = doc.documentElement;
var metaEl = doc.querySelector('meta[name="viewport"]');
var flexibleEl = doc.querySelector('meta[name="flexible"]');
var dpr = 0;
var scale = 0;
var tid;
var flexible = lib.flexible || (lib.flexible = {});
if (metaEl) {
console.warn("将根据已有的meta标签来设置缩放比例");
var match = metaEl.getAttribute("content").match(/initial\-scale=([\d\.]+)/);
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 / scale);
}
} else if (flexibleEl) {
var content = flexibleEl.getAttribute("content");
if (content) {
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
}
}
if (!dpr && !scale) {
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)) {
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 / dpr;
}
docEl.setAttribute("data-dpr", dpr);
if (!metaEl) {
metaEl = doc.createElement("meta");
metaEl.setAttribute("name", "viewport");
metaEl.setAttribute(
"content",
"initial-scale=" +
scale +
", maximum-scale=" +
scale +
", minimum-scale=" +
scale +
", user-scalable=no"
);
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
} else {
var wrap = doc.createElement("div");
wrap.appendChild(metaEl);
doc.write(wrap.innerHTML);
}
}
function refreshRem() {
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
var rem = width / 10;
docEl.style.fontSize = rem + "px";
flexible.rem = win.rem = rem;
}
win.addEventListener(
"resize",
function () {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
},
false
);
win.addEventListener(
"pageshow",
function (e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
},
false
);
if (doc.readyState === "complete") {
doc.body.style.fontSize = 12 * dpr + "px";
} else {
doc.addEventListener(
"DOMContentLoaded",
function (e) {
doc.body.style.fontSize = 12 * dpr + "px";
},
false
);
}
refreshRem();
flexible.dpr = win.dpr = dpr;
flexible.refreshRem = refreshRem;
flexible.rem2px = function (d) {
var val = parseFloat(d) * this.rem;
if (typeof d === "string" && d.match(/rem$/)) {
val += "px";
}
return val;
};
flexible.px2rem = function (d) {
var val = parseFloat(d) / this.rem;
if (typeof d === "string" && d.match(/px$/)) {
val += "rem";
}
return val;
};
3. 如何方便的计算rem
使用 Less 编写的混合宏(Mixin),用于将像素值转换为 rem 单位。rem 是一种相对单位,基于根元素的字体大小,通常用于响应式设计中,以确保在不同设备和屏幕尺寸下具有一致的布局和样式。
.remMixin(){
@functions: ~`(function(){
function convert(size){
return typeof size === 'string' ? +size.replace('px', '') : size;
}
const baseFontSize = convert('75px');
this.px2rem = function(size){
return convert(size) / baseFontSize + 'rem';
}
this.px2remImp = function(size) {
return (convert(size) / baseFontSize) + 'rem !important';
}
})()`
}
.remMixin();