文末
逆水行舟不进则退,所以大家要有危机意识。
同样是干到35岁,普通人写业务代码划水,榜样们深度学习拓宽视野晋升管理。
这也是为什么大家都说35岁是程序员的门槛,很多人迈不过去,其实各行各业都是这样都会有个坎,公司永远都缺的高级人才,只用这样才能在大风大浪过后,依然闪耀不被公司淘汰不被社会淘汰。
为了帮助大家更好温习重点知识、更高效的准备面试,特别整理了《前端工程师核心知识笔记》电子稿文件。
内容包括html,css,JavaScript,ES6,计算机网络,浏览器,工程化,模块化,Node.js,框架,数据结构,性能优化,项目等等。
269页《前端大厂面试宝典》
包含了腾讯、字节跳动、小米、阿里、滴滴、美团、58、拼多多、360、新浪、搜狐等一线互联网公司面试被问到的题目,涵盖了初中级前端技术点。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
前端面试题汇总
/* 竖屏 */
@media all and (orientation: portrait) {
/* 自定义样式 */
}
复制代码
支持弹性滚动
在苹果系统上非<body>
元素的滚动操作可能会存在卡顿,但安卓系统不会出现该情况。通过声明overflow-scrolling:touch
调用系统原生滚动事件优化弹性滚动
,增加页面滚动的流畅度。
body {
-webkit-overflow-scrolling: touch;
}
.elem {
overflow: auto;
}
复制代码
禁止滚动传播
与桌面端浏览器
不一样,移动端浏览器
有一个奇怪行为。当页面包含多个滚动区域时,滚完一个区域后若还存在滚动动量则会将这些剩余动量传播到下一个滚动区域,造成该区域也滚动起来。这种行为称为滚动传播。
若不想产生这种奇怪行为可直接禁止。
.elem {
overscroll-behavior: contain;
}
复制代码
禁止屏幕抖动
对于一些突然出现滚动条的页面,可能会产生左右抖动的不良影响。在一个滚动容器里,打开弹窗就隐藏滚动条,关闭弹窗就显示滚动条,来回操作会让屏幕抖动起来。提前声明滚动容器的padding-right
为滚动条宽度,就能有效消除这个不良影响。
每个移动端浏览器
的滚动条宽度都有可能不一致,甚至不一定占位置,通过以下方式能间接计算出滚动条的宽度。100vw
为视窗宽度,100%
为滚动容器内容宽度,相减就是滚动条宽度,妥妥的动态计算。
body {
padding-right: calc(100vw - 100%);
}
复制代码
禁止长按操作
有时不想用户长按元素呼出菜单进行点链接
、打电话
、发邮件
、保存图片
或扫描二维码
等操作,声明touch-callout:none
禁止用户长按操作。
有时不想用户复制粘贴
盗文案,声明user-select:none
禁止用户长按操作和选择复制。
- {
/* pointer-events: none; / / 微信浏览器还需附加该属性才有效 */
user-select: none; /* 禁止长按选择文字 */
-webkit-touch-callout: none;
}
复制代码
但声明user-select:none
会让<input>
和<textarea>
无法输入文本,可对其声明user-select:auto
排除在外。
input,
textarea {
user-select: auto;
}
复制代码
禁止字体调整
旋转屏幕可能会改变字体大小,声明text-size-adjust:100%
让字体大小保持不变。
- {
text-size-adjust: 100%;
}
复制代码
禁止高亮显示
触摸元素会出现半透明灰色遮罩,不想要!
- {
-webkit-tap-highlight-color: transparent;
}
复制代码
禁止动画闪屏
在移动设备上添加动画,多数情况会出现闪屏,给动画元素的父元素构造一个3D环境
就能让动画稳定运行了。
.elem {
perspective: 1000;
backface-visibility: hidden;
transform-style: preserve-3d;
}
复制代码
美化表单外观
表单元素样式太丑希望自定义,appearance:none
来帮你。
button,
input,
select,
textarea {
appearance: none;
/* 自定义样式 */
}
复制代码
美化滚动占位
滚动条样式太丑希望自定义,::-webkit-scrollbar-*
来帮你。记住以下三个关键词就能随机应变了。
-
::-webkit-scrollbar:滚动条整体部分
-
::-webkit-scrollbar-track:滚动条轨道部分
-
::-webkit-scrollbar-thumb:滚动条滑块部分
::-webkit-scrollbar {
width: 6px;
height: 6px;
background-color: transparent;
}
::-webkit-scrollbar-track {
background-color: transparent;
}
::-webkit-scrollbar-thumb {
border-radius: 3px;
background-image: linear-gradient(135deg, #09f, #3c9);
}
复制代码
美化输入占位
输入框占位文本太丑,::-webkit-input-placeholder
来帮你。
input::-webkit-input-placeholder {
color: #66f;
}
复制代码
对齐输入占位
有强迫症的同学总会觉得输入框文本位置整体偏上,感觉未居中心里就痒痒的。桌面端浏览器
里声明line-height
等于height
就能解决,但移动端浏览器
里还是未能解决,需将line-height
声明为normal
才行。
input {
line-height: normal;
}
复制代码
对齐下拉选项
下拉框选项默认向左对齐,是时候改改向右对齐了。
select option {
direction: rtl;
}
复制代码
修复点击无效
在苹果系统上有些情况下非可点击元素监听click事件
可能会无效,针对该情况只需对不触发click事件
的元素声明cursor:pointer
就能解决。
.elem {
cursor: pointer;
}
复制代码
识别文本换行
多数情况会使用JS换行文本,那就真的Out
了。若接口返回字段包含\n
或<br>
,千万别替换掉,可声明white-space:pre-line
交由浏览器做断行处理。
- {
white-space: pre-line;
}
复制代码
开启硬件加速
想动画更流畅吗,开启GPU硬件加速
呗!
.elem {
transform: translate3d(0, 0, 0);
/* transform: translateZ(0); */
}
复制代码
描绘像素边框
万年话题,如何描绘一像素边框
?
.elem {
position: relative;
width: 200px;
height: 80px;
&::after {
position: absolute;
left: 0;
top: 0;
border: 1px solid #f66;
width: 200%;
height: 200%;
content: “”;
transform: scale(.5);
transform-origin: left top;
}
}
复制代码
控制溢出文本
万年话题,如何控制文本做单行溢出
和多行溢出
?
.elem {
width: 400px;
line-height: 30px;
font-size: 20px;
&.sl-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&.ml-ellipsis {
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}
}
复制代码
JS方向
禁止点击穿透
移动端浏览器
里点击操作会存在300ms
延迟,往往会造成点击延迟甚至点击无效,这个是众所周知的事情。
2007年
苹果发布首款iPhone
搭载的Safari
为了将桌面端网站能较好地展示在移动端浏览器
上而使用了双击缩放。该方案就是上述300ms
延迟的主要原因,当用户执行第一次单击后会预留300ms
检测用户是否继续执行单击,若是则执行缩放操作,若否则执行点击操作。鉴于该方案的成功,其他移动端浏览器
也复制了该方案,现在几乎所有移动端浏览器
都配备该功能。而该方案引发的点击延迟被称为点击穿透。
在前端领域里最早解决点击穿透是jQuery时代
的zepto
,估计现在大部分同学都未使用过zepto
,其实它就是移动端版本的jquery
。zepto
封装tap事件
能有效地解决点击穿透,通过监听document
上的touch事件
完成tap事件
的模拟,并将tap事件
冒泡到document
上触发。
在移动端浏览器
上不使用click事件
而使用touch事件
是因为click事件
有着明显的延迟,后续又出现fastclick
。该解决方案监听用户是否做了双击操作,可正常使用click事件
,而点击穿透就交给fastclick
自动判断。更多fastclick
原理可自行百度,在此不作过多介绍。
fastclick有现成的NPM包
,可直接安装到项目里。引入fastclick
可使用click事件
代替tap事件
,接入方式极其简单。
import Fastclick from “fastclick”;
FastClick.attach(document.body);
复制代码
禁止滑动穿透
移动端浏览器
里出现弹窗时,若在屏幕上滑动能触发弹窗底下的内容跟着滚动,这个是众所周知的事情。
首先明确解决滑动穿透需保持哪些交互行为,那就是除了弹窗内容能点击或滚动,其他内容都不能点击或滚动
。目前很多解决方案都无法做到这一点,全部解决方案都能禁止<body>
的滚动行为却引发其他问题。
-
弹窗打开后内部内容无法滚动
-
弹窗关闭后页面滚动位置丢失
-
Webview
能上下滑动露出底色
当打开弹窗时给<body>
声明position:fixed;left:0;width:100%
并动态声明top
。声明position:fixed
会导致<body>
滚动条消失,此时会发现虽然无滑动穿透,但页面滚动位置早已丢失。通过scrollingElement
获取页面当前滚动条偏移量并将其取负值且赋值给top
,那么在视觉上就无任何变化。当关闭弹窗时移除position:fixed;left:0;width:100%
和动态top
。
scrollingElement
可兼容地获取scrollTop
和scrollHeight
等属性,在移动端浏览器
里屡试不爽。document.scrollingElement.scrollHeight
可完美代替曾经的document.documentElement.scrollHeight || document.body.scrollHeight
,一眼看上去就是代码减少了。
该解决方案在视觉上无任何变化,完爆其他解决方案,其实就是一种反向思维和障眼法。该解决方案完美解决固定弹窗
和滚动弹窗
对<body>
全局滚动的影响,当然也可用于局部滚动容器里,因此很值得推广。
body.static {
position: fixed;
left: 0;
width: 100%;
}
复制代码
const body = document.body;
const openBtn = document.getElementById(“open-btn”);
const closeBtn = document.getElementById(“close-btn”);
openBtn.addEventListener(“click”, e => {
e.stopPropagation();
const scrollTop = document.scrollingElement.scrollTop;
body.classList.add(“static”);
body.style.top = -${scrollTop}px
;
});
closeBtn.addEventListener(“click”, e => {
e.stopPropagation();
body.classList.remove(“static”);
body.style.top = “”;
});
复制代码
支持往返刷新
点击移动端浏览器
的前进按钮
或后退按钮
,有时不会自动执行旧页面的JS代码,这与往返缓存
有关。这种情况在Safari
上特别明显,简单概括就是往返页面无法刷新。
往返缓存指浏览器为了在页面间执行前进后退操作时能拥有更流畅体验的一种策略,以下简称BFCache
。该策略具体表现为:当用户前往新页面前将旧页面的DOM状态保存在BFCache
里,当用户返回旧页面前将旧页面的DOM状态从BFCache
里取出并加载。大部分移动端浏览器
都会部署BFCache
,可大大节省接口请求的时间和带宽。
了解什么是BFCache
再对症下药,解决方案就在window.onunload
上做文章。
// 在新页面监听页面销毁事件
window.addEventListener(“onunload”, () => {
// 执行旧页面代码
});
复制代码
若在Vue SPA
上使用keep-alive
也不能让页面刷新,可将接口请求放到beforeRouteEnter()
里。
当然还有另一种解决方案。pageshow事件
在每次页面加载时都会触发,无论是首次加载还是再次加载都会触发,这就是它与load事件
的区别。pageshow事件
暴露的persisted
可判断页面是否从BFCache
里取出。
window.addEventListener(“pageshow”, e => e.persisted && location.reload());
复制代码
若浏览器不使用<meta http-equiv="Cache-Control" content="no-cache">
禁用缓存,该解决方案还是很值得一用。
解析有效日期
在苹果系统上解析YYYY-MM-DD HH:mm:ss
这种日期格式会报错Invalid Date
,但在安卓系统上解析这种日期格式完全无问题。
new Date(“2019-03-31 21:30:00”); // Invalid Date
复制代码
查看Safari
相关开发手册发现可用YYYY/MM/DD HH:mm:ss
这种日期格式,简单概括就是年月日必须使用/
衔接而不能使用-
衔接。当然安卓系统也支持该格式,然而接口返回字段的日期格式通常是YYYY-MM-DD HH:mm:ss
,那么需替换其中的-
为/
。
const date = “2019-03-31 21:30:00”;
new Date(date.replace(/-/g, “/”));
复制代码
修复高度坍塌
当页面同时出现以下三个条件时,键盘占位会把页面高度压缩一部分。当输入完成键盘占位消失后,页面高度有可能回不到原来高度,产生坍塌导致Webview
底色露脸,简单概括就是输入框失焦后页面未回弹。
-
页面高度过小
-
输入框在页面底部或视窗中下方
-
输入框聚焦输入文本
只要保持前后滚动条偏移量一致就不会出现上述问题。在输入框聚焦时获取页面当前滚动条偏移量,在输入框失焦时赋值页面之前获取的滚动条偏移量,这样就能间接还原页面滚动条偏移量解决页面高度坍塌。
const input = document.getElementById(“input”);
let scrollTop = 0;
input.addEventListener(“focus”, () => {
scrollTop = document.scrollingElement.scrollTop;
});
input.addEventListener(“blur”, () => {
document.scrollingElement.scrollTo(0, this.scrollTop);
});
复制代码
修复输入监听
在苹果系统上的输入框输入文本,keyup/keydown/keypress事件
可能会无效。当输入框监听keyup事件
时,逐个输入英文和数字会有效,但逐个输入中文不会有效,需按回车键才会有效。
此时可用input事件
代替输入框的keyup/keydown/keypress事件
。
简化回到顶部
曾几何时编写一个返回顶部
函数麻烦得要死,需scrollTop
、定时器
和条件判断
三者配合才能完成。其实DOM对象里隐藏了一个很好用的函数可完成上述功能,一行核心代码就能搞定。
该函数就是scrollIntoView,它会滚动目标元素的父容器使之对用户可见,简单概括就是相对视窗让容器滚动到目标元素位置。它有三个可选参数能让scrollIntoView
滚动起来更优雅。
-
behavior:动画过渡效果,默认
auto无
,可选smooth平滑
-
inline:水平方向对齐方式,默认
nearest就近对齐
,可选start顶部对齐
、center中间对齐
和end底部对齐
-
block:垂直方向对齐方式,默认
start顶部对齐
,可选center中间对齐
、end底部对齐
和nearest就近对齐
const gotopBtn = document.getElementById(“gotop-btn”);
openBtn.addEventListener(“click”, () => document.body.scrollIntoView({ behavior: “smooth” }));
复制代码
当然还可滚动到目标元素位置,只需将document.body
修改成目标元素的DOM对象。一行核心代码就能搞掂的事情为何还编写那么多代码去完成,不累吗?
简化懒性加载
与上述简化回到顶部一样,编写一个懒性加载
函数也同样需scrollTop
、定时器
和条件判断
三者配合才能完成。其实DOM对象里隐藏了一个很好用的函数可完成上述功能,该函数无需监听容器的scroll事件
,通过浏览器自身机制完成滚动监听。
该函数就是IntersectionObserver,它提供一种异步观察目标元素及其祖先元素或顶级文档视窗交叉状态的方法。详情可参照MDN文档,在此不作过多介绍。
懒性加载的第一种使用场景:图片懒加载。只需确认图片进入可视区域就赋值加载图片,赋值完成还需对图片停止监听。
复制代码
const imgs = document.querySelectorAll(“img.lazyload”);
const observer = new IntersectionObserver(nodes => {
nodes.forEach(v => {
if (v.isIntersecting) { // 判断是否进入可视区域
v.target.src = v.target.dataset.src; // 赋值加载图片
observer.unobserve(v.target); // 停止监听已加载的图片
}
});
});
imgs.forEach(v => observer.observe(v));
复制代码
懒性加载的第二种使用场景:下拉加载。在列表最底部部署一个占位元素且该元素无任何高度或实体外观,只需确认占位元素进入可视区域就请求接口加载数据。
-
复制代码
const bottom = document.getElementById(“bottom”);
const observer = new IntersectionObserver(nodes => {
const tgt = nodes[0]; // 反正只有一个
if (tgt.isIntersecting) {
console.log(“已到底部,请求接口”);
// 执行接口请求代码
}
})
bottom.observe(bottom);
最后
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
❤️ 谢谢支持,喜欢的话别忘了 关注、点赞哦。
rver = new IntersectionObserver(nodes => {
nodes.forEach(v => {
if (v.isIntersecting) { // 判断是否进入可视区域
v.target.src = v.target.dataset.src; // 赋值加载图片
observer.unobserve(v.target); // 停止监听已加载的图片
}
});
});
imgs.forEach(v => observer.observe(v));
复制代码
懒性加载的第二种使用场景:下拉加载。在列表最底部部署一个占位元素且该元素无任何高度或实体外观,只需确认占位元素进入可视区域就请求接口加载数据。
-
复制代码
const bottom = document.getElementById(“bottom”);
const observer = new IntersectionObserver(nodes => {
const tgt = nodes[0]; // 反正只有一个
if (tgt.isIntersecting) {
console.log(“已到底部,请求接口”);
// 执行接口请求代码
}
})
bottom.observe(bottom);
最后
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
❤️ 谢谢支持,喜欢的话别忘了 关注、点赞哦。
[外链图片转存中…(img-SN4eCQUh-1715758252452)]