黑马程序员技术交流社区

标题: 【西安校区】前端常见面试题分享(一) [打印本页]

作者: 逆风TO    时间: 2019-12-5 11:04
标题: 【西安校区】前端常见面试题分享(一)
一:什么是BFC?什么时候触发BFC?
 BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。
 ** BFC布局规则:**
 内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC的区域不会与float box重叠。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算
哪些元素会生成BFC:
1.根元素
2.float属性不为none
3.position为absolute或fixed
4.display为inline-block, table-cell, table-caption, flex, inline-flex
5.overflow不为visible
二:在地址栏输入网址敲回车发生了什么?
总的来说分为以下几个过程:
1、DNS解析:将域名解析为IP地址;根据IP地址找到对应的服务器;
2、TCP连接:TCP三次握手;
3、发生HTTP请求;
4、服务器处理请求并返回HTTP报文;
5、浏览器解析渲染页面;
6、断开连接:TCP四次挥手;
TCP三次握手的过程:
TCP就是通信协议
1、第一次握手由浏览器发起,告诉服务器我要发送请求;
2、第二次握手由服务器发起,告诉浏览器我准备接收了,你发送吧;
3、第三次握手由浏览器发起,告诉服务器,我马上发送,准备接收;
为什么要发起三次握手:
为了防止已失效的连接请求报文段突然又传送到服务端,因而产生错误
在TCP三次握手结束后,开始发送HTTP请求报文
请求报文由请求行、请求头、请求体三部分组成:

1.请求行包含请求方法、URL、协议版本
请求方法包含 8 种:
GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。
URL 即请求地址,由 <协议>://<主机>:<端口>/<路径>?<参数> 组成
协议版本即 http 版本号
2.请求头包含请求的附加信息,由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。
请求头部通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境和请求正文的有用信息。其中比如:Host,表示主机名,虚拟主机;Connection,HTTP/1.1 增加的,使用 keepalive,即持久连接,一个连接可以发多个请求;User-Agent,请求发出者,兼容性以及定制化需求。

3.请求体,可以承载多个请求参数的数据,包含回车符、换行符和请求数据,并不是所有请求都具有请求数据。
断开连接:TCP四次挥手;
当数据传送完毕,需要断开 TCP连接,此时发起 TCP 四次挥手。
1、第一次挥手:由浏览器发起,发送给服务器,我请求报文发送完了,你准备关闭吧;
2、第二次挥手:由服务器发起,告诉浏览器,我接收完请求报文,我准备关闭,你也准备吧;
3、第三次挥手:由服务器发起,告诉浏览器,我响应报文发送完毕,你准备关闭吧;
4、第四次挥手:由浏览器发起,告诉服务器,我响应报文接收完毕,我准备关闭,你也准备吧;
大概就是这样吧
三:什么是重绘什么是重流

重流: reflow, 重绘: repaint

重流必定导致重绘, 重绘不一定重流

布局改变,浏览器的尺寸,字体大小,元素的尺寸,元素的位置变化,CSS伪类激活,DOM操作会发生重流, 元素颜色等改变只会发生重绘
**下面是通过减少重流/重绘次数而优化页面性能的一些手段: **

减少js中的dom操作, 若必须, 则尽量将读取dom和写入dom的操作放在一起, 便于浏览器累积dom变动, 一次执行, 减少重绘.

缓存dom信息, 多次使用, 不要重复读取dom节点.

不要一项一项地改变样式, 尽量用 css class一次性改变样式.

使用documentFragment操作DOM

动画使用absolute或fixed定位. 不然重流会很严重.

只有在必要时才显示或隐藏元素, 这个操作必定会导致重流

使用window.requestAnimationFrame()可以把代码推迟到下一次重流时执行.

使用Virtual DOM(如 React / Vue)

四:函数防抖和函数节流
概念
函数防抖
当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间
函数节流
预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期
函数节流(throttle)与 函数防抖(debounce)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟,假死或卡顿的现象。

比如如下的情况:

window对象的resize、scroll事件
拖拽时的mousemove事件
文字输入、自动完成的keyup事件

**区别举个列子 **
函数防抖:如果有人进电梯(触发事件),那电梯将在10秒钟后出发(执行事件监听器),这时如果又有人进电梯了(在10秒内再次触发该事件),我们又得等10秒再出发(重新计时)。
函数节流 :保证如果电梯第一个人进来后,10秒后准时运送一次,这个时间从第一个人上电梯开始计时,不等待,如果没有人,则不运行
五:Vue中assets和static的区别
相同点:

assets和static两个都是存放静态资源文件。项目中所需要的资源文件图片,字体图标,样式文件等都可以放在这两个文件下,这是相同点
不相同点:

assets中存放的静态资源文件在项目打包时,也就是运行npm run build时会将assets中放置的静态资源文件进行打包上传,所谓打包简单点可以理解为压缩体积,代码格式化。而压缩后的静态资源文件最终也都会放置在static文件中跟着index.html一同上传至服务器

static中放置的静态资源文件就不会要走打包压缩格式化等流程,而是直接进入打包好的目录,直接上传至服务器。因为避免了压缩直接进行上传,在打包时会提高一定的效率,但是static中的资源文件由于没有进行压缩等操作,所以文件的体积也就相对于assets中打包后的文件提交较大点。在服务器中就会占据更大的空间。所以简单点使用建议如下:

将项目中template需要的样式文件js文件等都可以放置在assets中,走打包这一流程。减少体积。而项目中引入的第三方的资源文件如iconfoont.css等文件可以放置在static中,因为这些引入的第三方文件已经经过处理,我们不再需要处理,直接上传。

当然具体情况,具体分析,在不同的开发环境,不同的需求下,大家应针对不同具体情况采用合适方式。对两者的理解就简单总结这些。记录这些,只为记录自己的开发点击,望对大家有帮助。

六:computed与method的区别
上篇文章说了 computed与watch的区别 这里在补充一下computed与method的区别
computed是属性调用,而methods是函数调用
computed带有缓存功能,而methods不是

六:mvc,mvp和mvvm介绍及三大框架对比
上篇文章详细介绍了 MVVM 这里补充下mvc,mvp和mvvm的区别
mvc
View 传送指令到 Controller
Controller 完成业务逻辑后,要求 Model 改变状态
Model 将新的数据发送到 View,用户得到反馈
所有通信都是单向的。

mvp
MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。
各部分之间的通信,都是双向的。
View 与 Model 不发生联系,都通过 Presenter 传递。
View 非常薄,不部署任何业务逻辑,称为"被动视图"(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。

mvvm
MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。
唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。
这里面使用的设计模式有:观察者模式(发布订阅模式)、代理模式、工厂模式、单例模式。

七:SPA路由为history 刷新404 为什么 ?如何解决
原因:当路由模式为history的时候,服务器端会根据浏览器中的请求地址去匹配资源,此时服务器端没有对应的接口地址,因此返回404
解决办法:第一种:使用connect-history-api-fallback中间件

安装connect-history-api-fallback中间件

npm install --save connect-history-api-fallback

在app.js文件中增加以下代码:

const history = require('connect-history-api-fallback')
app.use('/', history());

重新启动服务
第二种方法:Internet Information Services (IIS)
1.安装 IIS UrlRewrite
在你的网站根目录中创建一个 web.config 文件,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Handle History Mode and custom 404/500" stopProcessing="true">
          <match url="(.*)" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

八:手写promise封装ajax请求
上代码:
// 使用promise实现一个简单的ajax

/**
* 首先,可能会使用到的xhr方法或者说属性
* onloadstart // 开始发送时触发
* onloadend   // 发送结束时触发,无论成功不成功
* onload      // 得到响应
* onprogress  // 从服务器上下载数据,每50ms触发一次
* onuploadprogress // 上传到服务器的回调
* onerror     // 请求错误时触发
* onabort     // 调用abort时候触发
* status      // 返回状态码
* setRequestHeader // 设置请求头
* responseType // 请求传入的数据
*/

// 默认的ajax参数
let ajaxDefaultOptions = {
  url: '#', // 请求地址,默认为空
  method: 'GET', // 请求方式,默认为GET请求
  async: true, // 请求同步还是异步,默认异步
  timeout: 0, // 请求的超时时间
  dataType: 'text', // 请求的数据格式,默认为text
  data: null, // 请求的参数,默认为空
  headers: {}, // 请求头,默认为空
  onprogress: function () {}, // 从服务器下载数据的回调
  onuploadprogress: function () {}, // 处理上传文件到服务器的回调
  xhr: null // 允许函数外部创建xhr传入,但是必须不能是使用过的
};

function _ajax(paramOptions) {
  let options = {};
  for (const key in ajaxDefaultOptions) {
    options[key] = ajaxDefaultOptions[key];
  }
  // 如果传入的是否异步与默认值相同,就使用默认值,否则使用传入的参数
  options.async = paramOptions.async === ajaxDefaultOptions.async ? ajaxDefaultOptions.async : paramOptions.async;
  // 判断传入的method是否为GET或者POST,否则传入GET 或者可将判断写在promise内部,reject出去
  options.method = paramOptions.method ? ("GET" || "POST") : "GET";
  // 如果外部传入xhr,否则创建一个
  let xhr = options.xhr || new XMLHttpRequest();
  // return promise对象
  return new Promise(function (resolve, reject) {
    xhr.open(options.method, options.url, options.async);
    xhr.timeout = options.timeout;
    // 设置请求头
    for (const key in options.headers) {
      xhr.setRequestHeader(key, options.headers[key]);
    }
    // 注册xhr对象事件
    xhr.responseType = options.dataType;
    xhr.onprogress = options.onprogress;
    xhr.onuploadprogress = options.onuploadprogress;
    // 开始注册事件
    // 请求成功
    xhr.onloadend = function () {
      if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
        resolve(xhr);
      } else {
        reject({
          errorType: "status_error",
          xhr: xhr
        });
      }
    };
    // 请求超时
    xhr.ontimeout = function () {
      reject({
        errorType: "timeout_error",
        xhr: xhr
      });
    }
    // 请求错误
    xhr.onerror = function () {
      reject({
        errorType: "onerror",
        xhr: xhr
      });
    }
    // abort错误(未明白,只知道是三种异常中的一种)
    xhr.onabort = function () {
      reject({
        errorType: "onabort",
        xhr: xhr
      });
    }
    // 捕获异常
    try {
      xhr.send(options.data);
    } catch (error) {
      reject({
        errorType: "send_error",
        error: error
      });
    }
  });
}


// 调用示例
_ajax({
  url: 'http://localhost:3000/suc',
  async: true,
  onprogress: function (evt) {
    console.log(evt.position / evt.total);
  },
  dataType: 'text/json'
}).then(
  function (xhr) {
    console.log(xhr.response);
  },
  function (e) {
    console.log(JSON.stringify(e))
  });







欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2