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>