撩课-Web大前端每天5道面试题-Day4
1. 如何实现瀑布流?
瀑布流布局的原理: ) 瀑布流布局要求要进行布置的元素等宽,
然后计算元素的宽度,
与浏览器宽度之比,得到需要布置的列数; ) 创建一个数组,长度为列数,
里面的值为已布置元素的总高度(最开始为0); ) 然后将未布置的元素依次布置到高度最小的那一列,
就得到了瀑布流布局; ) 滚动加载, scroll事件得到scrollTop,
与最后盒子的offsetTop对比,
符合条件就不断滚动加载。 瀑布流布局核心代码: /**
* 实现瀑布流的布局
* @param {string}parentBox
* @param {string}childBox
*/
function waterFull(parentBox, childBox) {
// 1. 求出父盒子的宽度
// 1.1 获取所有的子盒子
var allBox = $(parentBox).
getElementsByClassName(childBox);
// console.log(allBox); // 1.2 求出子盒子的宽度
var boxWidth = allBox[].offsetWidth;
// console.log(boxWidth); // 1.3 获取窗口的宽度
var clientW = document.
documentElement.clientWidth;
// console.log(clientW); // 1.4 求出总列数
var cols = Math.floor(clientW / boxWidth);
// console.log(cols); // 1.5 父盒子居中
$(parentBox).style.width = cols * boxWidth + 'px';
$(parentBox).style.margin = '0 auto'; // 2. 子盒子定位
// 2.1 定义变量
var heightArr = [], boxHeight = ,
minBoxHeight = , minBoxIndex = ; // 2.2 遍历所有的子盒子
for (var i = ; i < allBox.length; i++) {
// 2.2.1 求出每一个子盒子的高度
boxHeight = allBox[i].offsetHeight;
// console.log(boxHeight);
// 2.2.2 取出第一行盒子的高度放入高度数组中
if (i < cols) { // 第一行
heightArr.push(boxHeight);
} else { // 剩余行的盒子
// 2.2.3 取出数组中最矮的高度
minBoxHeight = _.min(heightArr);
// 2.2.4 求出最矮高度对应的索引
minBoxIndex = getMinBoxIndex(heightArr, minBoxHeight);
// 2.2.5 盒子定位
allBox[i].style.position = 'absolute';
allBox[i].style.left = minBoxIndex * boxWidth + 'px';
allBox[i].style.top = minBoxHeight + 'px';
// 2.2.6 更新最矮的高度
heightArr[minBoxIndex] += boxHeight; }
}
} /**
* 根据内容取出在数组中对应的索引
* @param {object}arr
* @param {number}val
* @returns {boolean}
*/ function getMinBoxIndex(arr, val) {
for (var i = ; i < arr.length; i++) {
if (arr[i] === val) return i;
}
} /**
* 判断是否具备加载子盒子的条件
* @returns {boolean}
*/
function checkWillLoadImage() {
// 1. 获取最后一个盒子
var allBox = $('main').getElementsByClassName('box');
var lastBox = allBox[allBox.length - ]; // 2. 求出高度
var lastBoxDis = lastBox.offsetHeight * 0.5 + lastBox.offsetTop; // 3. 求出窗口的高度
var clientH = document.documentElement.clientHeight; // 4. 求出页面滚动产生的高度
var scrollTopH = scroll().top; // 5. 对比
return lastBoxDis <= clientH + scrollTopH;
}
2. 原生JS都有哪些方式可以实现两个页面间的通信?
) 通过url地址栏传递参数;
例如:点击列表页中的每一条数据,
我们跳转到同一个详细页面,
但是根据点击的不一样可以看到
不同的内容,这样的话我们就可以
在URL中传递不同的值来区分了; ) 通过本地存储 cookie、localeStorage、
sessionStroage...,例如:京东的登录,
我们在登录页登录完成后,
把用户信息存储到本地,
然后在其它页面中如果需要使用的话,
我们直接从本地的存储数据中拿
出来用即可; ) 使用iframe在A页面中嵌入B页面,
这样的话,在A中可以通过一些属性
和方法实现和B页面的通信; ) 利用postMessage实现页面间通信,
父窗口往子窗口传递信息,
子窗口往父窗口传递信息。
3. 原生JS动态向一个div中插入1000个div标签,如何实现?
此题主要考性能! ) 可以用JS中的createElement创建div,
每当创建一个就把它添加到div中,
但会造成引发回流的次数太多; ) 使用字符串拼接的方式,
把1000个div都拼接完成后,
统一的添加到页面中,
但会对div原有的元素标签产生影响:
原来标签绑定的事件都消失了 ) 综合1和2可以使用文档碎片方式来处理。 追问:如果是创建1000万个呢? 可采用的方案: 数据分批异步加载
) 首先把前两屏幕的数据量
(例如:300条)先获取到,
然后使用字符串拼接或者文档碎片
的方式绑定到页面中; ) 当浏览器滚动到指定的区域的
时候在加载300条...以此类推。
4. 程序出现bug了,你是如何调试的?
) 在控制台加断点,
F10->逐过程 F11->逐语句;
) 在代码重点的位置加入
console.log输出对应的值来进行调试;
) debugger调试;
) 代码分割还原调试;
) 异常捕获机制, 记录运行日志;
) 单元测试。
5. 开发中是如何进行性能优化的?
现在框架(vue, react,...)、构建工具(webpack, ...)
已经给我们解决掉大部分的性能优化问题,
面试时, 可以就你了解的框架来深入剖析,
但此题应该是考原生JS的范畴,
参考答案如下: ) 雅虎35条性能优化黄金定律;
) JS代码优化:
a. 项目中的JS/CSS文件最好一个页面只用一个,
需要把JS/CSS进行合并压缩,
并且减少页面中的垃圾冗余代码。
项目的资源文件在服务器上最好
做一下GZIP压缩。 b. 解除文件缓存;
我们修改代码并上传,
如果之前页面访问过该网站,
很有可能不能立即见效;
我们在引入CSS/JS文件的时候,
在文件名的后面加上版本号(加时间戳),
比如:
<script src='itlike.com.js?_=202001...'></script>;
当我们上传新的文件后
把时间戳改一下就可以清除缓存了。 c. 移动端尽量少用图片:
icon能用svg画的不用图片;
静态资源图:做布局的时候就能确定下来的图片,
比如:
) css sprite图片合并
(针对于小图片)
) 做图片延迟加载
(针对于大图片 头部的长条图片、背景大图...),
开始给一张默认的小的图片
(最好维持在10kb以内)
) base64
(存在问题: 页面的代码太臃肿了,以后维护不好操作);
如果项目中由于图片太大实在解决不了,
改成base64就解决了 d. 动态数据图:
通过ajax从后台读取回来的图片 , 图片懒加载; e. 音视频文件的优化:
加载页面的时候,尽量不要加载音视频文件,
当页面中的其他资源加载完成后,
再开始加载音视频文件;
目前移动端经常给音视频做的优化是:
走直播流文件(音频后缀名是m3u8格式); f. 减少页面资源请求的次数:
如果当前只是一个宣传页,
或者是一个简单的页面,
使用的css和js可以采用内嵌式开发; g. ajax数据请求分批请求,
例如:一次要请求10000条数据的话,
我们每一次只请求100条,第一屏幕肯定能看全了,
当页面滚动到对应的其它屏幕的时候,
在加载下一个100条... h. 做数据的二次缓存,
能用CSS3做动画的绝对不用JS,
能使用transform尽量使用,
能用animation的进行不用transition...
尽量减少同步操作,多用异步操作;
能使用原生JS自己编写的,
绝对不用插件或者框架;
6. 如何实现电商网站中的楼层效果?
) 封装缓动动画函数;
) 点击切换, 滚动切换, 联动处理; 核心代码如下: // 3. 监听GPS上的li的点击
for (var j = ; j < olLis.length; j++) {
(function (index) {
var olLi = olLis[index];
olLi.onmousedown = function () { isClick = true; // 3.1 排他
for (var m = ; m < olLis.length; m++) {
olLis[m].className = ''
}
addClass(this, 'current'); // 3.2 让楼层滚动起来
buffer(
document.documentElement,
{'scrollTop': index * client().height},
function () {
isClick = false;
})
}
})(j)
} // 4. 监听文档的滚动
window.onscroll = function (ev1) {
// 4.1 没有点击产生的滚动
if (!isClick) {
// 4.2 获取页面产出的头部滚动的高度
var roll = Math.ceil(scroll().top);
console.log(roll);
// 4.3 遍历
for (var i = ; i < olLis.length; i++) {
// 4.4 判断
if (roll >= ulLis[i].offsetTop) {
for (var m = ; m < olLis.length; m++) {
olLis[m].className = ''
}
addClass(olLis[i], 'current');
}
}
} } 缓动动画函数: /**
* 缓动动画(撩课学院)
* @param {object}obj
* @param {object}json
* @param {function}fn
*/
function buffer(obj, json, fn) {
// 1.1 清除定时器
clearInterval(obj.timer);
// 1.2 设置定时器
var begin = , target = , speed = ;
obj.timer = setInterval(function () {
// 1.3.0 旗帜
var flag = true;
for (var k in json) {
// 1.3 获取初始值
if ("opacity" === k) { // 透明度
begin = parseInt(parseFloat(getCSSAttrValue(obj, k)) * );
target = parseInt(parseFloat(json[k]) * );
} else if ("scrollTop" === k) {
begin = Math.ceil(obj.scrollTop);
target = parseInt(json[k]);
} else { // 其他情况
begin = parseInt(getCSSAttrValue(obj, k)) || ;
target = parseInt(json[k]);
}
// 1.4 求出步长
speed = (target - begin) * 0.2;
// 1.5 判断是否向上取整
speed = (target > begin)
? Math.ceil(speed)
: Math.floor(speed);
// 1.6 动起来
if ("opacity" === k) { // 透明度
// w3c的浏览器
obj.style.opacity = (begin + speed) / ;
// ie 浏览器
obj.style.filter = 'alpha(opacity:' + (begin + speed) + ')';
} else if ("scrollTop" === k) {
obj.scrollTop = begin + speed;
} else if ("zIndex" === k) {
obj.style[k] = json[k];
} else {
obj.style[k] = begin + speed + "px";
} // 1.5 判断
if (begin !== target) {
flag = false;
}
} // 1.3 清除定时器
if (flag) {
clearInterval(obj.timer);
// 判断有没有回调函数
if (fn) {
fn();
}
}
}, );
}
撩课-Web大前端每天5道面试题-Day4的更多相关文章
- 撩课-Web大前端每天5道面试题-Day10
1. px和em的区别? px和em都是长度单位; 区别是: px的值是固定的,指定是多少就是多少, 计算比较容易. em得值不是固定的,并且em会继承父级元素的字体大小. 浏览器的默认字体高都是16 ...
- 撩课-Web大前端每天5道面试题-Day1
1. var的变量提升的底层原理是什么? JS引擎的工作方式是: 1) 先解析代码,获取所有被声明的变量: 2)然后在运行.也就是说分为预处理和执行两个阶段. 变量提升:所有变量的声明语句都会被提升到 ...
- 撩课-Web大前端每天5道面试题-Day11
1. 如何手写一个JQ插件? 方式一: $.extend(src) 该方法就是将src合并到JQ的全局对象中去: $.extend({ log: ()=>{alert('撩课itLike');} ...
- 撩课-Web大前端每天5道面试题-Day31
1.web storage和cookie的区别? Web Storage的概念和cookie相似, 区别是它是为了更大容量存储设计的. Cookie的大小是受限的, 并且每次你请求一个新的页面的时候C ...
- 撩课-Web大前端每天5道面试题-Day25
1.web前端开发,如何提高页面性能优化? 内容方面: .减少 HTTP 请求 (Make Fewer HTTP Requests) .减少 DOM 元素数量 (Reduce the Number o ...
- 撩课-Web大前端每天5道面试题-Day7
1. 你能描述一下渐进增强和优雅降级之间的不同吗? 定义: 优雅降级(graceful degradation): 一开始就构建站点的完整功能, 然后针对浏览器测试和修复 渐进增强(progressi ...
- 撩课-Web大前端每天5道面试题-Day30
1.什么叫优雅降级和渐进增强? 优雅降级: Web站点在所有新式浏览器中都能正常工作, 如果用户使用的是老式浏览器, 则代码会针对旧版本的IE进行降级处理了, 使之在旧式浏览器上以某种形式降级体验却不 ...
- 撩课-Web大前端每天5道面试题-Day23
1.为什么用Nodejs,它有哪些优缺点? 优点: 事件驱动,通过闭包很容易实现客户端的生命活期. 不用担心多线程,锁,并行计算的问题 V8引擎速度非常快 对于游戏来说,写一遍游戏逻辑代码,前端后端通 ...
- 撩课-Web大前端每天5道面试题-Day16
1.for循环中的作用域问题? 写出以下代码输出值,尝试用es5和es6的方式进行改进输出循环中的i值. ; i<=; i++) { setTimeout(function timer() { ...
随机推荐
- break与continue语句
1.break:立即退出循环 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- HTML防止input回车提交表单
原链接:https://blog.csdn.net/ligang2585116/article/details/44699567 自动提交情况说明: 1.默认情况下,单个输入框,无论按钮的type=& ...
- 关于Mybatis 反向生成后 查询结果全部为null 解决办法
今天遇到了一个问题,就是mybatis通过反向生成工具 生成的pojo类(实体类) xml文件 以及Mapper之后查询时结果为null 我写的代码怎么看都没有错 就是没有结果 后来在排除错误的时候发 ...
- 超详细!CentOS 7 + Hadoop3.0.0 搭建伪分布式集群
超详细!CentOS 7 + Hadoop3.0.0 搭建伪分布式集群 ps:本文的步骤已自实现过一遍,在正文部分避开了旧版教程在新版使用导致出错的内容,因此版本一致的情况下照搬执行基本不会有大错误. ...
- Java多线程(汇聚页)
Java多线程(汇聚页) Java多线程总结
- 前端必学内容:webpack3快速入门 1-23节内容参考
前端必学内容:webpack(模块打包器) webpack3 学习内容,点击即可到达 (1).webpack快速入门——如何安装webpack及注意事项 (2).webpack快速入门——webpac ...
- Python的科学计算包matplotlib setup
回想起大学四年 专业一直使用matlab,然而我却没在PC上装成功过,以前懒于思考这种数学工具的作用,直到最近,大学同学研究生要毕业了,几经交流,和自己阅读了一些机器学习的教材之后,发觉科学计算包和画 ...
- leetcode-852-山脉数组的峰顶索引
题目描述: 我们把符合下列属性的数组 A 称作山脉: A.length >= 3 存在 0 < i < A.length - 1 使得A[0] < A[1] < ... ...
- shiro原理及其运行流程介绍
shiro原理及其运行流程介绍 认证执行流程 1.通过ini配置文件创建securityManager 2.调用subject.login方法主体提交认证,提交的token 3.securityMan ...
- python科学计算与可视化
一.Numpy 库 NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库. 引用: import ...