• Web大前端面试题-Day4


    1. 如何实现瀑布流?

    瀑布流布局的原理:
    1) 瀑布流布局要求要进行布置的元素等宽,   然后计算元素的宽度,   与浏览器宽度之比,得到需要布置的列数;
    2) 创建一个数组,长度为列数,   里面的值为已布置元素的总高度(最开始为0);
    3) 然后将未布置的元素依次布置到高度最小的那一列,   就得到了瀑布流布局;
    4) 滚动加载, scroll事件得到scrollTop,     与最后盒子的offsetTop对比,   符合条件就不断滚动加载。 瀑布流布局核心代码:

    /** * 实现瀑布流的布局 * @param {string}parentBox * @param {string}childBox */
    function waterFull(parentBox, childBox) {    
       //  1. 求出父盒子的宽度    //  1.1 获取所有的子盒子    var allBox = $(parentBox).    getElementsByClassName(childBox);      // 1.2 求出子盒子的宽度    var boxWidth = allBox[0].offsetWidth;      // 1.3 获取窗口的宽度    var clientW = document.    documentElement.clientWidth;      // 1.4 求出总列数    var cols = Math.floor(clientW / boxWidth);      // 1.5 父盒子居中    $(parentBox).style.width = cols * boxWidth + 'px';
       // 2. 子盒子定位    $(parentBox).style.margin = '0 auto';      //  2.1 定义变量    var heightArr = [], boxHeight = 0,        minBoxHeight = 0, minBoxIndex = 0;  
       // 2.2 遍历所有的子盒子      for (var i = 0; i < allBox.length; i++) {  
       // 2.2.1 求出每一个子盒子的高度              boxHeight = allBox[i].offsetHeight;    // 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';
       // 2.2.6 更新最矮的高度      allBox[i].style.left = minBoxIndex * boxWidth + 'px';      allBox[i].style.top = minBoxHeight + 'px';                  heightArr[minBoxIndex] += boxHeight;        }    } }

    /** * 根据内容取出在数组中对应的索引 * @param {object}arr * @param {number}val * @returns {boolean} */

    function getMinBoxIndex(arr, val) {    
       for (var i = 0; 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 - 1];  
    // 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都有哪些方式可以实现两个页面间的通信?

    1)  通过url地址栏传递参数;
        例如:点击列表页中的每一条数据,
        我们跳转到同一个详细页面,
        但是根据点击的不一样可以看到
        不同的内容,这样的话我们就可以
        在URL中传递不同的值来区分了;
    
    2)  通过本地存储 cookie、localeStorage、
        sessionStroage...,例如:京东的登录,
        我们在登录页登录完成后,
        把用户信息存储到本地,
        然后在其它页面中如果需要使用的话,
        我们直接从本地的存储数据中拿
        出来用即可;
    
    3)  使用iframe在A页面中嵌入B页面,
        这样的话,在A中可以通过一些属性
        和方法实现和B页面的通信;
    
    4)  利用postMessage实现页面间通信, 
        父窗口往子窗口传递信息, 
        子窗口往父窗口传递信息。

    3. 原生JS动态向一个div中插入1000个div标签,如何实现?

    此题主要考性能!
    
    1)  可以用JS中的createElement创建div,
        每当创建一个就把它添加到div中, 
        但会造成引发回流的次数太多;
    
    2)  使用字符串拼接的方式,
        把1000个div都拼接完成后,
        统一的添加到页面中, 
        但会对div原有的元素标签产生影响:
        原来标签绑定的事件都消失了
    
    3)  综合1和2可以使用文档碎片方式来处理。
    
    追问:如果是创建1000万个呢?
    
    可采用的方案: 数据分批异步加载
    1)  首先把前两屏幕的数据量
        (例如:300条)先获取到,
        然后使用字符串拼接或者文档碎片
        的方式绑定到页面中; 
    
    2)  当浏览器滚动到指定的区域的
        时候在加载300条...以此类推。

    4. 程序出现bug了,你是如何调试的?

    1)  在控制台加断点,
        F10->逐过程  F11->逐语句;
    2) 在代码重点的位置加入    
      console.log输出对应的值来进行调试;
    3) debugger调试;
    4) 代码分割还原调试;
    5) 异常捕获机制, 记录运行日志;
    6) 单元测试。

    5. 开发中是如何进行性能优化的?

    现在框架(vue, react,...)、构建工具(webpack, ...)
    已经给我们解决掉大部分的性能优化问题, 
    面试时, 可以就你了解的框架来深入剖析, 
    但此题应该是考原生JS的范畴,
    参考答案如下:
    1) 雅虎35条性能优化黄金定律;
    2) JS代码优化: a. 项目中的JS/CSS文件最好一个页面只用一个,    需要把JS/CSS进行合并压缩,    并且减少页面中的垃圾冗余代码。    项目的资源文件在服务器上最好    做一下GZIP压缩。   b. 解除文件缓存;    我们修改代码并上传,    如果之前页面访问过该网站,    很有可能不能立即见效;    我们在引入CSS/JS文件的时候,    在文件名的后面加上版本号(加时间戳),    比如:    
       <script src='itlike.com.js?_=202001...'></script>;    当我们上传新的文件后    把时间戳改一下就可以清除缓存了。  c. 移动端尽量少用图片:    icon能用svg画的不用图片;    静态资源图:做布局的时候就能确定下来的图片,    比如:    
       1) css sprite图片合并       (针对于小图片)    
       2) 做图片延迟加载       (针对于大图片 头部的长条图片、背景大图...),
          开始给一张默认的小的图片       (最好维持在10kb以内)    
       3) base64 (存在问题: 页面的代码太臃肿了,以后维护不好操作);         如果项目中由于图片太大实在解决不了,       改成base64就解决了    d. 动态数据图:     通过ajax从后台读取回来的图片 , 图片懒加载;  e. 音视频文件的优化:     加载页面的时候,尽量不要加载音视频文件,     当页面中的其他资源加载完成后,     再开始加载音视频文件;     目前移动端经常给音视频做的优化是:     走直播流文件(音频后缀名是m3u8格式);  f. 减少页面资源请求的次数:     如果当前只是一个宣传页,     或者是一个简单的页面,     使用的css和js可以采用内嵌式开发;  g. ajax数据请求分批请求,     例如:一次要请求10000条数据的话,     我们每一次只请求100条,第一屏幕肯定能看全了,     当页面滚动到对应的其它屏幕的时候,     在加载下一个100条...  h. 做数据的二次缓存,       能用CSS3做动画的绝对不用JS,     能使用transform尽量使用,     能用animation的进行不用transition...     尽量减少同步操作,多用异步操作;     能使用原生JS自己编写的,     绝对不用插件或者框架;  

    6. 如何实现电商网站中的楼层效果?

    1) 封装缓动动画函数;
    2) 点击切换, 滚动切换, 联动处理; 核心代码如下:
    // 3. 监听GPS上的li的点击
    for (var j = 0; j < olLis.length; j++) {    (function (index) {        
          var olLi = olLis[index];       olLi.onmousedown = function () {            isClick = true;          
               // 3.1 排他            for (var m = 0; 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 = 0; i < olLis.length; i++) {            
    // 4.4 判断
    if (roll >= ulLis[i].offsetTop) {                
    for (var m = 0; 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 = 0, target = 0, speed = 0;  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)) * 100);   target = parseInt(parseFloat(json[k]) * 100);  } else if ("scrollTop" === k) {   begin = Math.ceil(obj.scrollTop);   target = parseInt(json[k]);  } else {
    // 其他情况   begin = parseInt(getCSSAttrValue(obj, k)) || 0;   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) / 100;                
    // 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();      }    }  }, 20); }
  • 相关阅读:
    使用secureCRT连接VMware-Ubuntukylin虚拟机
    java使用POI jar包读写xls文件
    SimpleDateFormat 相关用法
    ORACLE之表
    ORACLE之PACKAGE-游标变量
    PHP多进程学习(三)__代码案例来了解父进程与子进程的执行顺序
    PHP多进程学习(二)__fork起多个子进程,父进程的阻塞与非阻塞
    PHP多进程学习(二)__来初步了解一下PHP多进程及简单demo
    Python学习【三】
    Python学习【二】
  • 原文地址:https://www.cnblogs.com/qingchunshiguang/p/10413685.html
Copyright © 2020-2023  润新知