前端面试基础问题

1、一个盒子水平垂直居中有哪些方法?

       1、利用 display:flex 布局

父元素设置 display:flex,justify-content:center,  align-item:center

        2、利用定位

给父元素设置相对定位,子元素设置绝对定位,子元素设置 top:50%,left:50%,margin-top:子元素高的一半,margin-left:子元素宽的一半

        3、利用 transform

父元素设置相对定位,子元素设置绝对定位,子元素设置  top:50%,left:50%, transform-translate(-50%  -50%)

        4、利用 margin:auto

父元素设置相对定位,子元素设置绝对定位,子元素设置 top:0,left:0,bottom:0,right:0,margin:auto

        5、利用 display:table-cell

父元素设置 display:table-cell,vertical-align: middle, text-align:center

子元素设置 display:inline-block

        6、计算子元素与父元素之间的空间距离

父元素 宽高500px,子元素宽高100px, 子元素设置  margin-top:200px,margin-left:200px

2、flex:1代表什么?flex的三个属性?

       flex:1 代表均匀分配元素

       flex:flex-grow    flex-shrink    flex-basis

  • flex-grow 属性用于设置或检索弹性盒子的扩展比率。属性值number 一个数字,规定项目将相对于其他灵活的项目进行扩展的量。默认值是 0。
  • flex-shrink 属性指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。
  • flex-basis 属性用于设置或检索弹性盒伸缩基准值。属性值number 一个长度单位或者一个百分比,规定灵活项目的初始长度。

3、rem 为什么可以实现自适应布局?

        rem(font size of the root element)是指相对于根元素的字体大小的单位。简单的说它就是一个相对单位。看到rem大家一定会想起em单位,em(font size of the element)是指相对于父元素的字体大小的单位。它们之间其实很相似,只不过一个计算的规则是依赖根元素一个是依赖父元素计算。rem是根据html的font-size大小来变化,正是基于这个出发,我们可以在每一个设备下根据设备的宽度设置对应的html字号,从而实现了自适应布局。

4、三次握手和四次挥手?

  • 三次握手通俗理解:

举个栗子:把客户端比作男孩,服务器比作女孩。用他们的交往来说明“三次握手”过程:

(1)男孩喜欢女孩,于是写了一封信告诉女孩:我爱你,请和我交往吧!;写完信之后,男孩焦急地等待,因为不知道信能否顺利传达给女孩。

(2)女孩收到男孩的情书后,心花怒放,原来我们是两情相悦呀!于是给男孩写了一封回信:我收到你的情书了,也明白了你的心意,其实,我也喜欢你!我愿意和你交往!;

写完信之后,女孩也焦急地等待,因为不知道回信能否能顺利传达给男孩。

(3)男孩收到回信之后很开心,因为发出的情书女孩收到了,并且从回信中知道了女孩喜欢自己,并且愿意和自己交往。然后男孩又写了一封信告诉女孩:你的心意和信我都收到了,谢谢你,还有我爱你!

女孩收到男孩的回信之后,也很开心,因为发出的情书男孩收到了。由此男孩女孩双方都知道了彼此的心意,之后就快乐地交流起来了~~

这就是通俗版的“三次握手”,期间一共往来了三封信也就是“三次握手”,以此确认两个方向上的数据传输通道是否正常。

  • 四次挥手通俗理解:

举个栗子:把客户端比作男孩,服务器比作女孩。通过他们的分手来说明“四次挥手”过程

 (1)“第一次挥手”:日久见人心,男孩发现女孩变成了自己讨厌的样子,忍无可忍,于是决定分手,随即写了一封信告诉女孩。

 (2)“第二次挥手”:女孩收到信之后,知道了男孩要和自己分手,怒火中烧,心中暗骂:你算什么东西,当初你可不是这个样子的!于是立马给男孩写了一封回信:分手就分手,给我点时间,我要把你的东西整理好,全部还给你!
男孩收到女孩的第一封信之后,明白了女孩知道自己要和她分手。随后等待女孩把自己的东西收拾好。

 (3)“第三次挥手”:过了几天,女孩把男孩送的东西都整理好了,于是再次写信给男孩:你的东西我整理好了,快把它们拿走,从此你我恩断义绝!

 (4)“第四次挥手”:男孩收到女孩第二封信之后,知道了女孩收拾好东西了,可以正式分手了,于是再次写信告诉女孩:我知道了,这就去拿回来!

5、常见状态码?

 2XX——表明请求被正常处理了

       1、200 OK:请求已正常处理。

       2、204 No Content:请求处理成功,但没有任何资源可以返回给客户端,一般在只需要从客户端往服务器发送信息,而对客户端不需要发送新信息内容的情况下使用。

       3、206 Partial Content:是对资源某一部分的请求,该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求。响应报文中包含由Content-Range指定范围的实体内容。

3XX——表明浏览器需要执行某些特殊的处理以正确处理请求

        4、301 Moved Permanently:资源的uri已更新,你也更新下你的书签引用吧。永久性重定向,请求的资源已经被分配了新的URI,以后应使用资源现在所指的URI。

        5、302 Found:资源的URI已临时定位到其他位置了,姑且算你已经知道了这个情况了。临时性重定向。和301相似,但302代表的资源不是永久性移动,只是临时性性质的。换句话说,已移动的资源对应的URI将来还有可能发生改变。

        6、303 See Other:资源的URI已更新,你是否能临时按新的URI访问。该状态码表示由于请求对应的资源存在着另一个URL,应使用GET方法定向获取请求的资源。303状态码和302状态码有着相同的功能,但303状态码明确表示客户端应当采用GET方法获取资源,这点与302状态码有区别。

当301,302,303响应状态码返回时,几乎所有的浏览器都会把POST改成GET,并删除请求报文内的主体,之后请求会自动再次发送。

        7、304 Not Modified:资源已找到,但未符合条件请求。该状态码表示客户端发送附带条件的请求时(采用GET方法的请求报文中包含If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任一首部)服务端允许请求访问资源,但因发生请求未满足条件的情况后,直接返回304.。

        8、307 Temporary Redirect:临时重定向。与302有相同的含义。

4XX——表明客户端是发生错误的原因所在。

       9、400 Bad Request:服务器端无法理解客户端发送的请求,请求报文中可能存在语法错误。

      10、401 Unauthorized:该状态码表示发送的请求需要有通过HTTP认证(BASIC认证,DIGEST认证)的认证信息。

      11、403 Forbidden:不允许访问那个资源。该状态码表明对请求资源的访问被服务器拒绝了。(权限,未授权IP等)

      12、404 Not Found:服务器上没有请求的资源。路径错误等。

5XX——服务器本身发生错误

      13、500 Internal Server Error:貌似内部资源出故障了。该状态码表明服务器端在执行请求时发生了错误。也有可能是web应用存在bug或某些临时故障。

      14、503 Service Unavailable:抱歉,我现在正在忙着。该状态码表明服务器暂时处于超负载或正在停机维护,现在无法处理请求。

6、Vue的生命周期?

     1、创建前(beforeCreate)

对应的钩子函数为beforeCreate。此阶段为实例初始化之后,此时的数据观察和事件机制都未形成,不能获得DOM节点。

     2、创建后(created)

对应的钩子函数为created。在这个阶段vue实例已经创建,仍然不能获取DOM元素。

     3、载入前(beforeMount)

对应的钩子函数是beforemount,在这一阶段,我们虽然依然得不到具体的DOM元素,但vue挂载的根节点已经创建,下面vue对DOM的操作将围绕这个根元素继续进行;beforeMount这个阶段是过渡性的,一般一个项目只能用到一两次。

     4、载入后(mounted)

对应的钩子函数是mounted。mounted是平时我们使用最多的函数了,一般我们的异步请求都写在这里。在这个阶段,数据和DOM都已被渲染出来。

     5、更新前(beforeUpdate)

对应的钩子函数是beforeUpdate。在这一阶段,vue遵循数据驱动DOM的原则;beforeUpdate函数在数据更新后虽然没立即更新数据,但是DOM中的数据会改变,这是Vue双向数据绑定的作用。

     6、更新后(updated)

对应的钩子函数是updated。在这一阶段DOM会和更改过的内容同步。

     7、销毁前(beforeDestroy)

对应的钩子函数是beforeDestroy。在上一阶段vue已经成功的通过数据驱动DOM更新,当我们不在需要vue操纵DOM时,就需要销毁Vue,也就是清除vue实例与DOM的关联,调用destroy方法可以销毁当前组件。在销毁前,会触发beforeDestroy钩子函数。

     8、销毁后(destroyed)

对应的钩子函数是destroyed。在销毁后,会触发destroyed钩子函数。

vue的生命周期的思想贯穿在组件开发的始终,通过熟悉其生命周期调用不同的钩子函数,我们可以准确地控制数据流和其对DOM的影响;vue生命周期的思想是Vnode和MVVM的生动体现和继承。

7、created和mounted的区别?

created没有挂载,mounted挂载完成         

  • created的时候,它的html节点都没有渲染出来
  • mounted的时候,可以进行数据请求,数据绑定,因为这时候它的html结构已经出来了,可以将数据绑定到DOM结构上面

8、组件传值分为?

组件传值分为父传子、子传父、兄弟组件之间的传值

  • 父传子:主要是通过v-bind绑定一个变量名称,在子组件里面用props接收

子组件(Children.vue):

<template>
    <section>
        父组件传过来的消息是:{{myMsg}}
    </section>
</template>

<script>
    export default {
        name: "Children",
        components: {},
        props:['msg'],
        data() {
            return {
                myMsg:this.msg
            }
        },
        methods: {}
    }
</script>

父组件(Parent.vue):

<template>
  <div class="parent">
    <Children :msg="message"></Children>
  </div>
</template>

<script>
import Children from '../components/Children'

export default {
  name: 'Parent',
  components: {
      Children
  },
  data() {
      return {
          message:'hello world'
      }
  },
}
</script>
  • 子传父:在子组件中使用this.$emit(‘myEvent’) 触发,然后在父组件中使用@myEvent监听,通俗来讲,是在子组件里面绑定一个方法,将这个参数传入之后用$emit()传递出去【$emit里面的参数是父组件中定义的一个方法名称以及参数,父组件里面同时要定义好这个方法,接收到这个参数,然后进行使用就可以】        

子组件(Children.vue):

<template>
    <section>
        <br>
        <div @click="clickme">click me</div>
    </section>
</template>

<script>
    export default {
        name: "Children",
        components: {},
        data() {
            return {
                childNum:0
            }
        },
        methods: {
            clickme(){
                // 通过自定义事件addNum把值传给父组件
                this.$emit('addNum',this.childNum++)
            }
        }
    }
</script>

父组件(Parent.vue ):

<template>
    <div class="parent">
        这里是计数:{{parentNum}}
        <Children-Com @addNum="getNum"></Children-Com>
    </div>
</template>

<script>
    import ChildrenCom from '../components/Children'

    export default {
        name: 'Parent',
        components: {
            ChildrenCom
        },
        data() {
            return {
                parentNum: 0
            }
        },
        methods:{
            // childNum是由子组件传入的
            getNum(childNum){
                this.parentNum = childNum
            }
        }
    }
</script>
  • 兄弟组件间传值:运用自定义事件emit的触发和监听能力,定义一个公共的事件总线eventBus,通过它作为中间桥梁,我们就可以传值给任意组件了。而且通过eventBus的使用,可以加深emit的触发和监听能力。

EventBus.js:

import Vue from 'vue'
export default new Vue()

兄弟1(Children1.vue): 

<template>
    <section>
        <div @click="pushMsg">push message</div>
        <br>
    </section>
</template>

<script>
    import eventBus from './EventBus'
    export default {
        name: "Children1",
        components: {},
        data() {
            return {
                childNum:0
            }
        },
        methods: {
            pushMsg(){
            	// 通过事件总线发送消息
                eventBus.$emit('pushMsg',this.childNum++)
            }
        }
    }
</script>

兄弟2(Children2.vue): 

<template>
    <section>
        children1传过来的消息:{{msg}}
    </section>
</template>

<script>
    import eventBus from './EventBus'

    export default {
        name: "Children2",
        components: {},
        data() {
            return {
                msg: ''
            }
        },
        mounted() {
        	// 通过事件总线监听消息
            eventBus.$on('pushMsg', (children1Msg) => {
                this.msg = children1Msg
            })
        }
    }
</script>

9、keep-alive是怎么使用的?

      keep-alive用于保存组件的渲染状态。进行一个缓存,会多出来几个生命周期,在这些生命周期里面可以重新请求数据,因为缓存的情况不会自动刷新。

10、vue双向绑定的原理?

      Vue数据原理是通过数据劫持结合发布者-订阅者模式的方式来实现的,首先是对数据进行监听,然后当监听的属性发生变化时则告诉订阅者是否要更新,若更新就会执行对应的更新函数从而更新视图。

11、跨域是由哪几种方式实现的?

方法一、处理跨域的jsonp方法

JSONP原理

利用<script  src="xxx">元素的这个天然支持跨域的策略,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。

JSONP和AJAX对比

JSONP和Ajax相同,都是客户端向服务器端发送请求,从服务器端获取数据的方式。但Ajax属于同源策略,JSONP属于非同源策略(跨域请求)。

JSONP优缺点

JSONP优点是兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持get方法具有局限性。

JSONP的流程(以第三方API地址为例,不必考虑后台程序)

声明一个回调函数,其函数名(如fn)当做参数值,要传递给跨域请求数据的服务器,函数形参为要获取目标数据(服务器返回的data)。

创建一个 <script>标签,把那个跨域的API数据接口地址,赋值给script的src,还要在这个地址中向服务器传递该函数名(可以通过问号传参 :?callback=fn)。

服务器接收到请求后,需要进行特殊的处理:把传递进来的函数名和它需要给你的数据拼接成一个字符串,例如:传递进去的函数名是fn,它准备好的数据是 fn([{"name":"jianshu"}])。

最后服务器把准备的数据通过HTTP协议返回给客户端,客户端再调用执行之前声明的回调函数(fn),对返回的数据进行操作。

<script type="text/javascript">
    function fn(data){
        alert(data.msg);
    }
</script>
<script type="text/javascript" src="http://crossdomain.com/jsonServerResponse?jsonp=fn">
其中 fn 是客户端注册的回调的函数,目的获取跨域服务器上的json数据后,对数据进行在处理。

最后服务器返回给客户端数据的格式为:

fn({ msg:'this  is  json  data'})
jQuery的jsonp形式

JSONP都是GET和异步请求的,不存在其他的请求方式和同步请求,且jQuery默认就会给JSONP的请求清除缓存。

$.ajax({
    url:"http://crossdomain.com/jsonServerResponse",
    dataType:"jsonp",
    type:"get",//可以省略
    jsonpCallback:"fn",//->自定义传递给服务器的函数名,而不是使用jQuery自动生成的,可省略
    jsonp:"jsonp",//->把传递函数名的那个形参callback变为jsonp,可省略
    success:function(data){
    console.log(data);}
});
方法二:处理跨域方法二——CORS

CORS原理

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

CORS优缺点

CORS要求浏览器(>IE10)和服务器的同时支持,是跨域的根本解决方法,由浏览器自动完成。

优点在于功能更加强大支持各种HTTP Method,缺点是兼容性不如JSONP。

只需要在服务器端做一些小小的改造即可:

header("Access-Control-Allow-Origin:*");
header("Access-Control-Allow-Methods:POST,GET");
例如:网站 http://localhost:63342/ 页面要请求 http://localhost:3000/users/userlist 页面,userlist页面返回json字符串格 {name:'Mr.Cao',gender:'male',career:'IT Education'}:

//在服务器端设置同源策略地址
router.get("/userlist",function(req, res,next){
    var user ={name:'Mr.Cao', gender:'male', career:'IT Education'};
    res.writeHeader(200,{"Access-Control-Allow-Origin":'http://localhost:63342'});
    res.write(JSON.stringify(user));
    res.end();
});
在响应头上添加 Access-Control-Allow-Origin 属性,指定同源策略的地址。同源策略默认地址是网页的本身。只要浏览器检测到响应头带上了CORS,并且允许的源包括了本网站,那么就不会拦截请求响应。

header("Access-Control-Allow-Origin:*");  
//    *  :表示所有其他的域可以向当前域发送请求
 
//或者
 
header("Access-Control-Allow-Origin:http://test.com:80(相同默认不写)");    
//  http://test.com:80 表示指定具体的这个域可以向当前域发送请求。
//当然也可以指定多个特定域名,多个地址的话用逗号分隔即可。
方法三:WebSocket

Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。同时,WebSocket 在建立连接时需要借助 HTTP 协议,连接建立好了之后 client 与 server 之间的双向通信就与 HTTP 无关了。

原生WebSocket API使用起来不太方便,我们使用Socket.io,它很好地封装了webSocket接口,提供了更简单、灵活的接口,也对不支持webSocket的浏览器提供了向下兼容。

//--------------------------------------前端代码:------------------------------
<div>user input:<input type="text">
</div><script src="./socket.io.js"></script>
<script>
var socket =io('http://www.domain2.com:8080');
// 连接成功处理
socket.on('connect', function(){   
    // 监听服务端消息
    socket.on('message',function(msg){
        console.log('data from server: ---> '+ msg);
    });
 
    // 监听服务端关闭
    socket.on('disconnect', function() { 
        console.log('Server socket has closed.');     
    });
});
    document.getElementsByTagName('input')[0].onblur = function() {
        socket.send(this.value);
    };
</script>
 
 
 
 
//---------------------------------------Nodejs socket后台:---------------------------
var http = require('http');
var socket =require('socket.io');
// 启http服务
var server = http.createServer(function(req, res) {
    res.writeHead(200, {'Content-type': 'text/html'});
    res.end();
});
server.listen('8080');
console.log('Server is running at port 8080...');
// 监听socket连接
socket.listen(server).on('connection', function(client) {
    
// 接收信息
    client.on('message', function(msg) {        
        client.send('hello:' + msg);
        console.log('data from client: ---> ' + msg);    
    });
    
// 断开处理
    client.on('disconnect', function() {
        console.log('Client socket has closed.');     
    });
});

方法四:postMessage

如果两个网页不同源,就无法拿到对方的DOM。典型的例子是iframe窗口和 window.open方法打开的窗口,它们与父窗口无法通信。HTML5为了解决这个问题,引入了一个全新的API:跨文档通信 API(Cross-document messaging)。这个API为window对象新增了一个 window.postMessage 方法,允许跨窗口通信,不论这两个窗口是否同源。

postMessage方法的第一个参数是具体的信息内容,第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为 *,表示不限制域名,向所有窗口发送。

接下来我们看个例子: http://localhost:63342/index.html页面向 http://localhost:3000/message.html传递“跨域请求信息”

//发送信息页面 http://localhost:63342/index.html
<html lang="en">  
<head>    
<meta charset="UTF-8">      
<title>跨域请求</title>   
</head>  
<body>      
<iframe src="http://localhost:3000/users/reg" id="frm"></iframe>      
<input type="button" value="OK" οnclick="run()">  
</body>  
</html>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值