React方向的前端面试题

1、React的生命周期?

React中只有类组件有生命周期可言。

其中包含三个状态:

Mounting:此时已经插入了真实的DOM;

Updating:正在被重新渲染;

Unmounting:已经移出真实的DOM。

生命周期的方法:

  1. componentWillMount:在渲染之前调用,在客户端也在服务器端;
  2. componentDidMount:在第一次渲染后调用,只在客户端;之后组件已经生成了对应的DOM结构,可以通过this.getDomNode()来访问。还可以在此时进行数据的异步请求操作;
  3. shouldComponentUpdate:它返回一个布尔值,在组件接受到一个新的props或者state时调用,不更新组件时调用;
  4. componentWillUpdate:接收到新的数据状态还未渲染时调用;
  5. componentDidUpdate:在完成更新数据的渲染之后调用;
  6. componentWillReceiveProps:在组件接收到新的props时调用;
  7. componentWillUnmount:在组件被卸载之前调用;

2、ES6的新特性?

看这里

3、有如下代码:一共有两层div,父元素的高度是400px,让里面的子元素垂直水平居中?

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>水平垂直居中</title>
    <style>
        #father{
            height:400px;
            background:teal;
            display:flex;
            justify-content: center;
            align-items: center;
            
        }
        #son{
            background:red;
        }
    </style>
</head>
<body>
    <div id="father">
        我是1
        <div id="son">
            我是2
        </div>
    </div>
</body>
</html>

实现效果:

React方向的前端面试题

其他常用的水平垂直实现:

 

以上介绍有八种方式,比较常用的三种方法:

  • 固定宽度+左右margin为auto;
  • inline-block属性是无法让元素水平居中,他的关键之处要在元素的父容器中设置text-align的属性为“center”
  • 浮动+相对定位;
  • 绝对定位+left+margin-left(负值)+top
    .ele {
        position: absolute;
        width: 宽度值;
        left: 50%;
        top:50%;
        margin-left: -(宽度值/2);
    } 
  • CSS3的flex:让父元素形成弹性盒子,再然后给子元素添加margin:auto,完成元素的垂直水平居中,这种方法也常用,

  • CSS3的width:fit-content实现水平居中方法+左右margin为auto

  • 设置父元素的元素类型为table-cell类型,设置表格的垂直对齐方式为居中,再给子元素添加margin:0 auto 完成元素的垂直水平居中,这种方法不常用,

  • 不定元素宽高的情况下,子元素设置行高(line-height=height),完成元素的垂直居中,再然后利用文本水平对齐方式text-align方法,完成水平居中,这中方法是最简单的,也是我们经常用的.

  • line-height 不是块级元素的情况下,使用它还是比较简单的
  • 绝对定位+负margin 兼容性好
  • flex 如果你不考虑兼容的情况下,建议使用它,灵活

4、数组常用的方法?

  • 1、Array.map():此方法是将数组中的每个元素调用一个提供的函数,返回了一个新数组,结果并没有改变原来的数组
  • 2、Array.forEach():此方法是将数组中的每一个元素执行并且传进提供的函数,没有返回值。原数组改变了。
  • 3、Arrat.filter():此方法是将数组的每一个元素进行判断,将满足条件的元素组成的新数组返回。
  • 4、Array.every():此方法是将所有元素进行判断返回一个布尔值,所有元素都满足判断条件,则返回true。
  • 5、Array.some():此方法是将所有元素判断返回一个布尔值,如果存在元素都满足判断条件,则返回true.
  • 6、Array.reduce():此方法是所有元素调用返回函数,返回值为最后结果,传入值必须是函数的类型;
  • 7、Array.push():此方法是往数组的后面添加新元素,此方法改变了数组的长度;
  • 8、Aarry.pop():此方法是在数组后面删除最后一个元素,并返回数组,此方法改变了数组的长度
  • 9、Array.shift():此方法是删除数组的第一个元素,并且返回数组,此方法改变了数组的长度。
  • 10、Array.unshift():此方法是将一个或者多个元素添加到数组的开头,并且返回一个新的数组;
  • 11、Array.concat():可以将多个数组拼接成一个数组;
  • 12、Array.isArray():判断一个对象是不是一个数组,返回的是布尔值。
  • 13、Array.toString():可以将数组转化为包含逗号d额字符串。将原数组变为字符串。
  • 14、Array.join():讲数组转化为以特定字符相隔的字符串。将原数组变为字符串。
  • 15、Array.splice(开始的位置,删除的个数,【要替换上去的元素】):万能的方法,可以实现增删改。

5、forEach和map的异同?

  • 相同:都是数组可以调用的方法;都是可以遍历数组元素,并且在回调的函数里对它们做一些改变
  • 区别:map返回新数组,没有改变原来的数组;forEach返回了新数组,并且改变了原来的数组。

map不会改变原数组,只是给原数组创建了一个引用,并且将改变后的引用作为返回值返回

6、http状态码举例?

http状态码分类:(5种)

1**:信息,服务器收到请求,需要请求者继续执行操作;

2**:成功,操作被成功接收并处理;

3**:重定向,需要进一步的操作来完成请求;

4**:客户端错误,请求包含发错误或无法完成请求;

5**:服务器错误,在请求过程中中服务器发生错误;

比较典型的

  • 200:请求成功;
  • 203:NonAuthoritative Information。非授权信息。但是请求成功。返回的meta数据不在原始的服务器而是存储在一个副本里。
  • 204:No Content.无内容。服务器成功处理,但是没有返回数据内容,在没有更新网页的前提下,可以确保网页显示当前 数据文档信息。
  • 301:资源(网页)等被转移到其他的URL;
  • 302:Found.临时移动。与301类似。但是资源只是被临时移动。客户端应该继续使用原来的请求地址。
  • 400:Bad Request.客户端的请求参数语法错误,后端无法解析。
  • 401:Unauthorized:当前客户端的用户需要身份认证。
  • 403:Forbidden。服务端能理解此请求但是拒绝了。
  • 404:请求的资源(网页)不存在;
  • 405:Method Not Allowed。客户的请求方式不支持,禁止。
  • 406:Not Acceptable。服务器无法根据客户端的请求特性完成请求。
  • 415:Unsupported Media Type。服务器不支持客户端的请求附带的媒体格式。
  • 500:内部的服务器错误,无法完成请求。
  • 503:Sevice Unavailable。由于超载或系统难维护,服务器暂时无法处理请求。

7、position的几个取值和区别?

  • static:静态。正常文档流中。
  • relative:相对定位。在正常文档流中,相对于当前元素之前的位置来定位。
  • absolute:绝对定位。脱离了正常的文档流。相对于离它最近的一个父元素(是相对定位的一个元素)来定位。
  • fixed:固定定位。没有脱离文档流。相对于浏览器的左上角来定位。

8、React中父子组件,兄弟组件的通信?

父子组件:

父组件中:<Child  msg={this.state.msg}>

子组件中用this.props.msg获取。

 

9、对react的高阶组件的理解?

用自己的语言来叙述。

Higher-Order Components

高阶组件是一个函数(而不是组件),它接受一个组件作为参数,返回一个新的组件。这个新的组件会使用你传给它的组件作为子组件 .返回新组件时可以回传一些原参数的扩展值。

详情请看这里。

10、对token的理解?token为什么不用显式的写在参数中?

理解:

  • Token 的中文有人翻译成 “令牌”,意思就是,你拿着这个令牌,才能过一些关卡。
  • taoken的验证流程:

客户端使用用户名跟密码请求登录;

服务器收到请求,去验证用户名和密码;

验证成功后,服务器签发一token,再把这个token发送给客户端;

客户端收到token后把它存储起来,比如放在cookie里面或者local storage里;

客户端每次向服务器发起请求资源的时候都要带着服务器签发的token;

  • 服务器收到请求,然后去验证客户端请求里面的token,若验证成功,就向客户端返回请求的数据。
  • token的作用:

   防止表单重复提交

Anti CSRF 攻击(跨站点请求伪造)

  • 原理

两者在原理上都是通过session token来实现。客户端请求页面时,服务器会随机生成一个随机数token,并且将token放置到session中,然后将token发给客户端(一般通过构造hidden表单)。下次客户端提交请求时,token会随着表单一起提交到服务端。

然后,如果应用于“Anti CSRF攻击“,则服务器会对token值进行验证,判断是否和session中的token值相等,若相等,则可以证明请求有效,不是伪造的。不过,如果,应用于“防止表单重复提交”,服务器端第一次验证相同后,会将session的token重新更新,若用户重复提交,第二次的验证判断将失败,因为用户携带token与服务器端的session里面的token不一致。

上面的session应用相对安全,但也是繁琐,同事当多页面请求时,必须采用多token同时生成的方法,这样占用更多资源,执行效率会降低。因此,也可以用cookie存储验证信息的方法来替代session token。比如,应对“重复提交”时,当第一次提交后便把已经提交的信息写到cookie中,当第二次提交时,由于cookie已经有提交记录,因此第二次提交会失败。不过,cookie有个致命弱点,如果cookie被劫持(XSS攻击很容易得到用户法人cookie)那么有一次的game over,黑客将直接实现CSRF攻击,安全和高效是相对的,具体问题,具体分析。

请求头携带token的原因:

在使用JSON Web Token作为单点登录的验证媒介时,为保证安全性,建议将JWT的信息存放在HTTP的请求头中,并使用https对请求链接进行加密传输

11、csrf和xxs的了解?

名称解释:

[1] XSS 攻击:跨站脚本攻击(Cross Site Scripting),恶意攻击者往 Web 页面里插入恶意 Script 代码,当用户浏览该页之时,嵌入其中 Web 里面的 Script 代码会被执行,从而达到恶意攻击用户的目的。

[2] CSRF 攻击:CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者 Session Riding,通常缩写为 CSRF 或者 XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与 XSS 非常不同,XSS 利用站点内的信任用户,而 CSRF 则通过伪装来自受信任用户的请求来利用受信任的网站。与 XSS 攻击相比,CSRF 攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比 XSS 更具危险性。

12、嵌套的高阶组件的实现思想?

每一个高阶组件函数执行之后中所返回的组件,刚好可以作为下一个高阶组件的参数继续执行,而并不会影响基础组件中所获得的新能力。

13、用promise写一个简单的字符串单个打印字母的函数?

// 一般的回调函数解决
function printStr(callback){
    setTimeout(function(){
        callback('abcdefg');
    },1000);
};

printStr(function(data){
    for(let item of data){
        console.log('item',item);
    }
})
// promise 实现
function printStr2(str){
    var p=new Promise(function(resolve,reject){
        //做一些异步操作
    
        setTimeout(function(){
          for(let item of str){
                resolve(item)
           }
        },1000)    
    })
    return p;
}
let str1="abcdefg";
printStr2(str1).then((item)=>{
    console.log('item',item)
})

14、普通函数和箭头函数的区别?

 

  • 箭头函数没有arguments,如果要用,可以用 rest 参数代替 (注意在node环境下是有arguments的)
  • 函数体内部的this指向不同

箭头函数的this指向上层对象,不能通过call,apply,bind来改变。箭头函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

普通函数的this是调用它的对象决定的,也可以通过call,apply,bind来改变this的指向。 

  • 箭头函数没有构造函数,不能用new关键字。
  • 箭头函数没有原型属性(prototype),不能继承
  • 箭头函数的单个参数,可以省略外部的小括号,以及return.

15、px,em,rem三个的区别?

  • px

px像素(Piexl)。相对长度单位。像素px是相对于显示器屏幕的分辨率而言的。

px的特点:

  1. IE无法调整那些以px为单位的字体的大小
  2. 国外的大部分网站能够调整的原因是他们使用了em或者rem作为字体单位;
  3. 火狐能够调整px、em、rem,但是96%以上的中国用户使用的是ie内核的浏览器。
  • em

em是相对长度单位。针对于当前对象内文本的字体尺寸,若当前对行内文本字体大小武规定,则相对于浏览器默认的字体尺寸。

em的特点:

  1. em的值不是固定的;
  2. em会继承父级元素的字体大小。

注意:

任意的浏览器的默认字体高度都是16px,所有未经过调整的浏览器都符合:1em=16px。那么12px=0.75em,10px=635em。为了简化font-size的换算,需要在css中的body选择器中声明"font-size:62.5%;",这就使得em的值变为:1em=16px*62.5%=10px,这样12px是1.2em,也就是只要将原来的px数值除以10,然后换上em作为单位就行了。

总结:

  1. body的选择器中声明font-size:62.5%;
  2. 将原来的px除以10,然后换上em为单位;
  3. 重新计算那些被放大的字体的em数值,避免字体大小重复声明。
  • rem

rem是CSS3的新增的一个长度单位(root em,根em),这个单位引起了广泛关注。这个单位和em有什么区别呢?区别在于使用rem为元素设定字体大小时,仍然是相对大小,但是她相对的只是HTML根元素。这个单位可谓是集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素内的fon-size的大小,就可以实现成比例的调整所有字体的大小,又可以避免字体大小逐层符合的连锁反应。目前,除了IE8以及更早的版本外,所有的浏览器均已支持rem。对于不支持它的浏览器,应对的方法也很简单,就是多写一个绝对单位的声明。这些浏览器会忽略用rem设定的字体大小。下面就是一个例子:

p{font-size:14px; font-size:0.875rem;}

注意:选择使用什么字体单位主要由你的项目来决定;如果你的用户都是用最新版的浏览器,那推荐使用rem,如果要考虑兼容性,那就是用px,或两者都使用。

px于rem的选择?

对于只需要适配少部分手机设备,而且分辨率对页面影响不大的,使用px即可;

对于需要是各种移动设备的,使用rem,例如,只需要适配Iphone和ipad等分辨率差别较大的设备

上一篇:一篇文章带你了解CSS单位相关知识


下一篇:<b>和<strong>的区别 <i>和<em>的区别