//基本布局
*{
margin: 0;
padding: 0;
}
.outer{
height: 200px;
}
.left{
background-color: gold;
height: 200px;
}
.right{
background-color: blue;
height: 200px;
}
</style>
<body>
<div class="outer">
<div class="left">left</div>
<div class="right">right</div>
</div>
</body>
/* 浮动 */
.outer .left{
float: left;
width: 200px;
}
.outer .right{
width: auto;
margin-left: 200px;
}
/* flex */
.outer {
display: flex;
}
.outer .left{
/* 索取父元素剩余空间 值越大索取越多 */
flex-grow: 0;
/* 收缩值默认为1 */
flex-shrink: 0;
/* 设置元素宽度 */
flex-basis: 200px;
}
.outer .right{
/* flex 是 flex-grow、flex-shrink、flex-basis的缩写 */
/* 1 1 auto */
flex: auto;
}
/* position */
.outer{
position: relative;
}
.outer .left{
position: absolute;
width: 200px;
}
.outer .right{
margin-left: 200px;
}
/* position again */
.outer{
position: relative;
}
.outer .left{
width: 200px;
}
.outer .right{
position: absolute;
left: 200px;
top: 0;
right: 0;
}
(2)三栏布局:垂直三栏布局,左右两栏宽度固定中间自适应
基础布局
<style>
*{
margin: 0;
padding: 0;
}
.outer, .left, .middle ,.right{
height: 200px;
}
.left{
background: blueviolet;
}
.middle{
background: blue;
}
.right{
background: yellow;
}
</style>
<body>
<div class="outer">
<div class="left">left</div>
<div class="middle">middle</div>
<div class="right">right</div>
</div>
</body>
/* 左右分别设置绝对定位中间设置外边距 */
.outer{
position: relative;
}
.outer .left{
position: absolute;
width: 100px;
}
.outer .right{
position: absolute;
width: 200px;
top: 0;
right: 0;
}
.outer .middle{
margin:0 200px 0 100px;
}
/* flex */
.outer{
display: flex;
}
.outer .middle{
flex: auto;
}
.outer .left{
flex: 0 0 100px;
}
.outer .right{
flex: 0 0 200px;
}
/* 浮动布局,但html中middle要放到最后 */
.outer .left{
width: 100px;
float: left;
}
.outer .right{
width: 200px;
float: right;
}
.outer .middle{
margin: 0 200px 0 100px;
}
和三栏布局要求相同,不过中间列要写在前面保证优先渲染。
1)两侧宽度固定,中间宽度自适应
2)中间部分在DOM结构上优先,以便先行渲染
3)允许三列中的任意一列成为最高列
4)只需要使用一个额外的 /
<style>
*{
margin: 0;
padding: 0;
}
body{
min-width: 500px;
}
.header, .footer{
background-color: tomato;
}
.footer{
clear: both;
}
.outer, .left, .middle ,.right{
height: 200px;
/* margin-bottom: 5px; */
}
.left{
background: blueviolet;
}
.middle{
background: blue;
}
.right{
background: yellow;
}
/* 圣杯布局 通过浮动和负边距实现 */
.outer{
padding: 0 200px 0 100px;
}
.outer .middle{
width: 100%;
float: left;
}
.outer .left{
width: 100px;
float: left;
margin-left: -100%;
position: relative;
left: -100px;
}
.outer .right{
width: 200px;
float: left;
margin-left: -200px;
position: relative;
left: 200px;
}
</style>
<body>
<div class="header">header</div>
<div class="outer">
<div class="middle">middle</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
<div class="footer">footer</div>
</body>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<style>
*{
margin: 0;
padding: 0;
}
body{
min-width: 500px;
}
.header, .footer{
background-color: tomato;
}
.footer{
clear: both;
}
.outer, .left, .middle ,.right{
height: 200px;
/* margin-bottom: 5px; */
}
.left{
background: blueviolet;
}
.middle{
background: blue;
}
.right{
background: yellow;
}
/* 双飞翼布局 middle在先 多一层div */
.outer .middle-wrapper{
width: 100%;
float: left;
}
.outer .middle{
margin: 0 200px 0 100px;
}
.outer .left{
width: 100px;
float: left;
margin-left: -100%;
}
.outer .right{
width: 200px;
float: left;
margin-left: -200px;
}
</style>
<body>
<div class="header">header</div>
<div class="outer">
<div class="middle-wrapper">
<div class="middle">middle</div>
</div>
<div class="left">left</div>
<div class="right">right</div>
</div>
<div class="footer">footer</div>
</body>
</html>
总结与思考
通过对圣杯布局和双飞翼布局的介绍可以看出,圣杯布局在DOM结构上显得更加直观和自然,且在日常开发过程中,更容易形成这样的DOM结构,而双飞翼布局在实现上由于不需要使用定位,所以更加简洁,且允许的页面最小宽度通常比圣杯布局更小。
其实通过思考不难发现,两者在代码实现上都额外引入了一个div标签,其目的都是为了既能保证中间栏产生浮动(浮动后还必须显式设置宽度),又能限制自身宽度为两侧栏留出空间。
从这个角度出发,如果去掉额外添加的div标签,能否完成相同的布局呢?答案是肯定的,不过这需要在兼容性上做出牺牲:
DOM结构
<div id="header"></div>
<div id="center" class="column"></div>
<div id="left" class="column"></div>
<div id="right" class="column"></div>
<div id="footer"></div>
1)使用calc()
.column {
float: left;
}
#center {
margin-left: 200px;
margin-right: 150px;
width: calc(100% - 350px);
}
通过calc()可以十分方便地计算出center应该占据的自适应宽度,目前calc()支持到IE9。
2.使用border-box
.column {
float: left;
}
#center {
padding-left: 200px;
padding-right: 150px;
box-sizing: border-box;
width: 100%;
}
使用border-box可以将center的整个盒模型宽度设置为父元素的100%宽度,此时再利用padding-left和padding-right可以自动得到中间栏的自适应宽度。不过需要注意的是,由于padding是盒子的一部分,所以padding部分会具有中间栏的背景色,当中间栏高于侧栏时,会出现中间栏背景色到侧边栏上去。
目前box-sizing支持到IE8。
3. 使用flex
这里使用flex还是需要与圣杯布局相同的DOM结构,不过在实现上将更加简单:
<!-- DOM结构 -->
<div id="container">
<div id="center"></div>
<div id="left"></div>
<div id="right"></div>
</div>
CSS代码如下:
#container {
display: flex;
}
#center {
flex: 1;
}
#left {
flex: 0 0 200px;
order: -1;
}
#right {
flex: 0 0 150px;
}
(4)实现一个三角形(通过border)
*{
margin: 0;
padding: 0;
}
div{
width:0;
height: 0;
border-style: solid;
margin: 0 auto;
}
/* 等腰直角三角形 */
.box{
border-width: 100px;
border-color: tomato transparent transparent transparent;
}
/*等边三角形 */
.box{
border-width: 100px 173px;
border-color: transparent tomato transparent transparent;
}
/* 等腰三角形 */
.box{
border-width: 100px 80px;
border-color: transparent transparent tomato transparent;
}
//或者
div{
width:0;
height:0;
border:30px solid transparent;
border-bottom:30px solid #000;
}
/* 其他 */
.box {
border-width: 100px 90px 80px 70px;
border-color: transparent transparent transparent tomato;
}
(5)实现一个自适应的圆
*{
margin: 0;
padding: 0;
}
.box{
//自适应
width: 30%;
padding-top: 30%;
margin :0 auto;
border: solid;
border-radius: 50%;
}
</style>
<body>
<div class="box"></div>
(6)实现文字溢出打点
//实现文字溢出打点
#test{
width:150px;
white-space:nowrap;
overflow:hidden;
text-overflow:ellipsis;
}
/**解析:
*首先需设置将文本强制在一行内显示,然后将溢出的文本通过overflow:hidden截断,
*并以text-overflow:ellipsis方式将截断的文本显示为省略号。
*/
(7)使用css实现一个宽高自适应的正方形
/* 相对于屏幕宽度的比例 */
div{
width: 30%;
height: 30vw;
background-color: rebeccapurple;
margin: 0 auto;
}
div{
width: 30%;
padding-top:30% ;
height: 0;
background-color: saddlebrown;
}
div{
width: 30%;
//触发BFC
overflow: hidden;
background-color: yellowgreen;
}
div::after{
content: "";
display: block;
/* 相当于div的width */
margin-top: 100%;
}
(8)实现一个 1/4 圆、任意弧度的扇形
基本设置
<body>
<div style = "display: flex;justify-content: space-around;">
<div class="sector"></div>
</div>
</body>
/* 通过border和border-radius实现四分之一圆 */
.sector{
width: 0;
height: 0;
border: 100px solid;
border-radius: 50%;
border-color: turquoise tomato tan thistle;
}
/* 类似三角形的做法加上父元素 overflow: hidden; 也可以实现任意弧度圆 */
.sector{
width: 100px;
height: 200px;
border-radius: 100px 100px 0 0;
overflow: hidden;
}
.sector::after{
content: "";
display: block;
height: 0;
width: 0;
border: solid;
border-width: 100px 58px 0 0;
border-color: tomato transparent;
transform: translate(42px,0);
}
/* 通过 skewY 实现一个60°的扇形 */
.sector4 {
height: 100px;
width: 100px;
border-top-right-radius: 100px;
overflow: hidden;
}
.sector4::after {
content: '';
display: block;
height: 100px;
width: 100px;
background: tomato;
transform: skewY(-30deg);
transform-origin: left bottom;
}
(9)
一个元素先进行沿着y轴平移再绕着z轴旋转和先绕着z轴旋转再沿着y轴平移,最后的位置显示相同嘛?
/* 先沿着y轴平移在绕x旋转 */
.box{
position: absolute;
margin: 200px;
width: 100px;
height: 100px;
border: 1px solid black;
transform: translateY(100px) rotateZ(45deg);
}
.wrapper{
margin: 200px;
position: absolute;
width: 100px;
height: 100px;
border: 1px solid red;
transform: rotateZ(45deg) translateY(100px);
}
(10)
display:none、visibility:hidden:、opacity:0之间的区别
display: none 彻底消失,render tree中也不存在(dom tree中存在);可能会引起reflow(重排)
visibility: hidden 渲染为空盒子,在render tree中存在;不会引起reflow;性能更好;也不会触发事件
opacity: 0 将元素隐藏起来,也不会改变页面布局,但是会触发点击事件
(11)实现居中的四种方式
a. flex:主轴(justify-content)和交叉轴(align-items)均为center
b· transform:(居中块)采用相对布局,top:50%,left:50%再加上transform: translate(-50%; -50%)实现水平垂直居中
c· margin负值:(居中块)采用相对布局 + top:50%,left:50% + margin-top: -height/2,margin-left: -width/2
d·绝对定位:父级节点相对定位,居中块绝对定位而且top:0;left:0;right:0;bottom:0;+margin:auto;
(12)浮动会造成哪些问题,为什么要清除浮动
1,浮动造成父元素高度坍塌:浮动会脱离当前文档流,父元素高度不会被撑开,计算父元素高度时不会加上浮动子元素的高度
2,浮动元素和非浮动元素重叠
//清除浮动利用伪元素的实现方式
.clearfix:before, .clearfix:after { content: ''; display: block; clear: both; }
(13)介绍一下css的盒子模型?盒模型分几种类型?如何切换盒模型?
css盒子模型 又称框模型(Box Model),包含了元素内容(content)、内边距(padding)、边框(border)、外边距(margin)
元素框的总高度=元素(element)的height + padding的上下边距的值+ margin的上下边距的值 +border的上下宽度 。
IE6混杂模式盒模型:最终显示的宽或高为设置width = content+padding*2+border*2
标准盒模型:width指的是content部分的宽度,不包括padding,border,margin
切换盒模型设置css3属性box-sizing,将标准盒模型切换IE6混杂模式盒模型:box-sizing:border-box。
box-sizing:content-box(默认值标准盒模型)
(14)transform和animation的区别?
transition属性是一个简单的动画属性,非常简单非常容易用。可以说它是animation的简化版本
Animation也是通过指定某一个属性(如width、left、transform等)在两个值之间如何过渡来
实现动画的,与Transition不同的是,Animation可以通过keyframe显式控制当前帧的属性值,
而Transition只能隐式来进行(不能指定每帧的属性值),所以相对而言Animation的功能更加灵
活。另外一个区别是Animation通过模拟属性值改变来实现动画,动画结束之后元素的属性没有变
化;而Transition确实改变了元素的属性值,动画结束之后元素的属性发生了变化.
(15)前端页面有哪三层构成,分别是什么?作用是什么?
答案:最准确的网页设计思路是把网页分成三个层次,即:结构层、表示层、行为层。 网页的结构
层由HTML或XHTML之类的标记语言负责创建。网页的表示层由CSS负责创建。 CSS对“如何显示有关
内容”的问题做出了回答。网页的行为层(负责回答“内容应该如何对事件做出反应”这一问题。这
是JavaScript语言和DOM主宰的领域。
(16)如何使连续的长字符串自动换行?
答案:#test{width:150px;word-wrap:break-word;}
解析:首先设置元素的固定宽度,然后设置文字超出显示为换行。word-wrap的break-word值允许单词内换行
(17)box-shadow传入参数分别代表的含义
1.X轴偏移量 2.Y轴偏移量 3.模糊程度 4.颜色
(18)元素设置display:inline-block属性基于元素的哪条基准线对齐?如果我们想让元素居中对齐如何设置?
基于元素的下基准线对齐,切换对齐方式我们可以利用vertical-align:middle;
(19)利用css3弹性盒子进行布局,需要为父级设置___a___属性与属性值,子元素默认呈行级元素排列,如果想让子元素竖直排列,可以设置___b___属性与属性值。
a -- display:flex; b -- flex-direction:column;
(20)水平垂直居中
```javascript
<!DOCTYPE html>
<html>
<head>
<title>水平垂直居中</title>
<style type="text/css">
.outer {
height: 200px;
width: 200px;
background: tomato;
margin: 10px;
float: left;
position: relative;
}
.inner {
height: 100px;
width: 100px;
background: black;
}
/*
* 通过 position 和 margin 居中
* 缺点:需要知道 inner 的长宽
*/
.inner1 {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px;
margin-left: -50px;
}
/*
* 通过 position 和 margin 居中 (2
*/
.inner2 {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
margin: auto;
}
/*
* 通过 flex 进行居中
*/
.outer3 {
display: flex;
justify-content: center;
align-items: center;
}
/**
* 通过 position 和 transform 居中
*/
.inner4 {
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
position: absolute;
}
</style>
</head>
<body>
<div class="outer outer1">
<div class="inner inner1"></div>
</div>
<div class="outer outer2">
<div class="inner inner2"></div>
</div>
<div class="outer outer3">
<div class="inner inner3"></div>
</div>
<div class="outer outer4">
<div class="inner inner4"></div>
</div>
</body>
</html>
(21)清除浮动
<!DOCTYPE html>
<html>
<head>
<title>清除浮动</title>
<style type="text/css">
.outer {
width: 200px;
background: tomato;
margin: 10px;
position: relative;
}
.inner {
height: 100px;
width: 100px;
background: pink;
margin: 10px;
float: left;
}
/* 伪元素 */
.outer1::after {
content: '';
display: block;
clear: both;
}
/* 创建 BFC */
.outer2 {
overflow: hidden;
}
</style>
</head>
<body>
<div class="outer outer1">
<div class="inner"></div>
</div>
<div class="outer outer2">
<div class="inner"></div>
</div>
</body>
(23)导航栏
一个 div 内部放很多水平 div ,并可以横向滚动。
(24)grid网格布局
display:grid/inline-grid
grid-template-columns:100px 200px 200px//每一列列宽
grid-template-rows:100px 200px 200px //每一行行高
grid-template-columns:100px 1fr 1fr 1fr//剩余三列平均分配大小
//行列之间的距离
(25)画一条0.5px的线
<meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/>
这样子就能缩放到原来的0.5倍,如果是1px那么就会变成0.5px
要记得viewport只针对于移动端,只在移动端上才能看到效果
transform: scale(0.5,0.5);
采用transform: scale()的方式
详细解释见这里
(26)link和import的区别
1.@import是 CSS 提供的语法规则,只有导入样式表的作用;link是HTML提供的标签,不仅可以加载 CSS 文件,还可以定义 RSS、rel 连接属性等。
2.加载页面时,link标签引入的 CSS 被同时加载;@import引入的 CSS 将在页面加载完毕后被加载。
3.@import是 CSS2.1 才有的语法,故只可在 IE5+ 才能识别;link标签作为 HTML 元素,不存在兼容性问题。
(27)animation和transation的区别
1.transition 需要去触发比如:点击事件、鼠标移入事件;而 animation 可以配合 @keyframe 可以不触发事件就触发这个动画
2.transition 触发一次播放一次;而 animation 则是可以设置很多的属性,比如循环次数,动画结束的状态等等;
3.transition关注的是样式属性的变化,属性值和时间的关系是一个三次贝塞尔曲线;而animation作用于元素本身而不是样式属性,可以使用关键帧的概念,可以实现更自由的动画效果
4.我们在用使用 aniamtion 的时候这样就可以改变很多属性,像我们改变了 width、height、postion 等等这些改变文档流的属性的时候就会引起,页面的回流和重绘,对性能影响就比较大,但是我们用 transition 的时候一般会结合 tansfrom 来进行旋转和缩放等不会生成新的位图,当然也就不会引起页面的重排了。
/* transition: 哪个属性动 运动在多长时间完成 延迟时间 运动类型;*/
animation-duration: 1s; /* 动画时间 */
animation-name: fillout; /* 通过name使用 */
animation-iteration-count: infinite; /* 循环次数,infinite(无限次循环) */
@keyframes fillout {
from {
width: 200px;
height: 200px;
}
to {
width: 400px;
height: 400px;
}
}
(28)BFC(块级格式上下文)
哪些元素会生成BFC?
float不为none;position:fixed/absolute;display:inline-block/table-cell/flex/;overflow不为visible;
BFC是为了防止浮动导致父级高度塌陷,避免外边距折叠。
渲染规则:
(1)BFC的区域不会与浮动元素的box重叠。
(2)BFC是一个独立的容器,外面的元素不会影响里面的元素。
(3)计算BFC高度的时候,浮动元素也会参与计算。
(29)CSS有哪些样式可以给子元素继承
可继承的:font-size,font-weight,line-height,color,cursor;
不可继承的:display,margin,border,padding,height
(30)行内元素,块级元素
行内:input span a img display:inline
块:p div header ul footer h1 table
空:br hr link mata input img(没有内容的)
**(31)HTML5页面结构语义化
原因:**易于修改,无障碍阅读,提高搜索的流量搜索引擎的排名
结构语义化:语义元素仅仅是页面结构的规范化,并不会对内容有本质影响。
(32)display:none和visibily:hidden
display:none:不显示对应的元素,文档布局中不在分配空间;
visiablity:hidden:隐藏对应元素,在文档中仍然保存原来空间
(33)怎么让chrome支持小于12px的文字
p{
font-size:10px
-webkit-transform:scale(0.8);
}
(34)动画的最小间隔时间是多久?
默认频率是60HZ,1S刷新60s, 1/60*100ms = 16.7ms
(35)css百分比问题
百分数是相对于父元素的width计算的,所以如果父元素的width以某种方式发生变化,百分数也会变化”。
参照父元素宽度的元素:padding margin width text-indent
参照父元素高度的元素:height
参照父元素属性:font-size line-height
特殊:相对定位的时候,top(bottom) left(right)参照的是父元素的内容区域的高度与宽度,而绝对定位的时候参照的是最近的定位元素包含padding的高度与宽度
(35)垂直居中
①div的显示方式设置为表格。父级用display:table;
子级用display:table-cell
vertical-align:middle
优点:子级可以动态的改变高度,当父级没有足够空间的时候不会被截断。
②使用绝对定位的div,top设置为50%,margin-top设置为负的高度的一半。
优点:适用于所有的浏览器,缺点:没有足够空间时,div会消失。
③父级div设置height:50%;margin-bottom为负的子级高度的一半,left浮动。子级设置clear:both清除浮动。
没有足够空间的时候不会被截断。
④固定宽度和高度的div,设置绝对定位,top:0,bottom:0;left:0;right:0;margin:auto
⑤单行文本有效:把line-height设置为height值使文本居中。
(1)原型链继承:无法实现多继承
(2)构造继承:多继承,只能继承父类实例的属性方法,不能继承原型上的属性方法。(复制父类的属性给子类)
(3)实例继承,拷贝继承
(4)组合继承:通过父类构造器继承父类的属性并保留传参的优点,将父类实例作为子类原型,实现函数复用。优点:可以继承实例的属性/方法,也可以继承原型的属性/方法。
(5)寄生组合继承(圣杯)
详情移步:JS继承
事件流是:html和js交互通过事件驱动实现的。
事件流是从页面中接收事件的顺序。
addeventListener:制定事件处理程序的操作。有三个参数(事件名,处理程序的函数,布尔值)
**事件委托:**不在直接dom上设置监听函数,在他的父元素上设置,通过事件冒泡,父监听子的事件触发,判断DOM类型作出响应。
就是能够读取其他函数内部变量的函数,或者说子函数在外调用,子函数躲在的父函数的作用域不会被释放。详情见闭包详解
clientHeight:可视区高度 不包含border和滚动条
offsetHeight:可视区高度 包含border和滚动条
scrollHeight:所有区域高度,包含因为滚动而被隐藏的部分
clientTop:border的宽度,一般为0
scrollTop:滚动后被隐藏的高度
(1)DOM操作,会导致重排重绘。避免使用 eval和 Function,减少作用域链查找(如果在循环中需要访问非本作用域下的变量时请在遍历之前用局部变量缓存该变量,并在遍历结束后再重写那个变量,这一点对全局变量尤其重要,因为全局变量处于作用域链的最顶端,访问时的查找次数是最多的。 )
(2)减少HTTP请求(每次http请求都会建立通信链路进行数据传输,服务器端每个http请求都要开启独立的线程处理,通信和服务的开销是昂贵的);减少http的手段:将js和css合并成一个文件,浏览器就只需要一次请求,图片合并雪碧图。恰当的缓存可以减少http请求(很少变化的图片资源可以直接通过 HTTP Header中的Expires设置一个很长的过期头 ;变化不频繁而又可能会变的资源可以使用 Last-Modifed来做请求验证。尽可能的让资源能够在缓存中待得更久。)
(3)使用浏览器缓存: 对一个网站而言,CSS、javascript、logo、图标这些静态资源文件更新的频率都比较低,而这些文件又几乎是每次http请求都需要的,如果将这些文件缓存在浏览器中,可以极好的改善性能。通过设置http头中的cache-control和expires的属性,可设定浏览器缓存,缓存时间可以是数天,甚至是几个月。
(4)减少cookie传输: 一方面,cookie包含在每次请求和响应中,太大的cookie会严重影响数据传输,因此哪些数据需要写入cookie需要慎重考虑,尽量减少cookie中传输的数据量。另一方面,对于某些静态资源的访问,如CSS、script等,发送cookie没有意义,可以考虑静态资源使用独立域名访问,避免请求静态资源时发送cookie,减少cookie传输次数。
(5)使用CDN:本质是一个缓存,将数据缓存在离用户最近的地方,使用户最快取得数据。
(6)反向代理:传统代理服务器位于浏览器一侧,代理浏览器将http请求发送到互联网上,而反向代理服务器位于网站机房一侧,代理网站web服务器接收http请求。论坛网站,把热门词条、帖子、博客缓存在反向代理服务器上加速用户访问速度,当这些动态内容有变化时,通过内部通知机制通知反向代理缓存失效,反向代理会重新加载最新的动态内容再次缓存起来。
此外,反向代理也可以实现负载均衡的功能,而通过负载均衡构建的应用集群可以提高系统总体处理能力,进而改善网站高并发情况下的性能。
浏览器的内核是多进程的。
包含了主进程,GPU进程,插件进程,浏览器渲染进程。
主进程:负责浏览器页面的展示,用户的交互,创建销毁其他进程。
GPU进程:3D渲染。
浏览器渲染进程:GUI渲染进程包括DOM解析,CSS解析,生成渲染树。JS引擎进程:执行js代码。事件触发:管
理者一个任务队列。异步http请求线程。定时触发器线程。
浏览器内核中线程之间的关系:
GUI线程和JS线程互斥:因为js是可以操作DOM的,如果在修改这些元素的同时渲染页面,那么渲染线程前后获得的元素数据可能就不一致了。
JS阻塞页面加载:js如果执行页面时间过长就会阻塞页面。
浏览器时多进程的优点:
默认新开一个tab页面,新建一个进程,所以单个tab页面崩溃不会影响到整个浏览器。
第三方插件崩溃不会影响到整个浏览器。
多进程可以充分利用现代CPU多核的优势。
提高浏览器稳定性。
啥是进程啥是线程啊?
进程是CPU资源分配的最小单位(是能拥有资源和独立运行的最小单位)
线程是CPU调度的最小单位(是建立在进程基础上的一次程序运行单位)
由于每个进程至少要做一件事,所以一个进程至少有一个线程。系统会给每个进程分配独立的内存,因此进程有它独立的资源。同一进程内的各个线程之间共享该进程的内存空间(包括代码段,数据集,堆等)。 进程可以理解为一个工厂不不同车间,相互独立。线程是车间里的工人,可以自己做自己的事情,也可以相互配合做同一件事情。
浏览器渲染进程
为了防止DOM渲染不一致,一个线程执行另一个会被挂起。
JS引擎线程和事件触发线程与Vue的nextTick息息相关。浏览器页面初次渲染完毕后,JS引擎线程结和事件触发线程的工作流程
(1)同步任务在JS引擎线程上执行,形成执行栈
(2)主线程外,事件触发线程管理者一个任务队列。只要异步任务有了运行结果,就在任务队列之中放置一个事件。
(3)执行栈中的同步任务执行完毕,系统会读取任务队列,将异步任务加入到主队列执行。
object boolean symbol null undefined string number
基本类型:boolean null undefined string number
undefined和null的区别
console.log(null==undefined); //true 因为两者都默认转换成了false
console.log(typeof undefined); //"undefined"
console.log(typeof null); //"object"
console.log(null===undefined); //false "==="表示绝对相等,null和undefined类型是不一样的,所以输出“false”
null默认转为为0;undefined转为NaN
undefined:调用一个值而该值没有赋值,缺少定义
null:表示没有对象,该处不应该有值。
1.let挂载的变量不会挂载到全局对象
2.不允许当前作用域范围内重复声明,块级作用域中let定义的变量外面不能访问。
3.使用let不会有变量提升。△底层实现上let声明的变量也会有提升,但是提升后会被放入暂时性死区,访问的变量位于暂时性死区会报错,运行到该变量的时候,会将变量从暂时性死区移出。
4.循环中使用let声明的循环变量用完后会被销毁。
1.给子级加上event.stopPropagation(不组织本身)
2.在事件处理函数中return false(不阻止事件冒泡本身)
3.event.target == event.currentTarget(触发事件的元素 == 绑定事件的元素)
setTimeout和setInterval的区别
setTimeout: 指定延期后调用函数,每次setTimeout计时到后就会去执行,然后执行一段时间后才继
续setTimeout,中间就多了误差,(误差多少与代码的执行时间有关)。
setInterval:以指定周期调用函数,而setInterval则是每次都精确的隔一段时间推入一个事件(但
是,事件的执行时间不一定就不准确,还有可能是这个事件还没执行完毕,下一个事件就来了)
requestanimationFrame:每秒60帧,可以准确执行每一帧。
setTimeout:1帧少于1/60秒,会出现卡顿,他上一帧执行完才会执行下一帧。
setTimeOut:指定的毫秒数后调用函数,只调用一次;
setInterval:在一定的时间内可多次调用;
setTimeout用于延迟执行某方法或功能
setInterval则一般用于刷新表单,对于一些表单的假实时指定时间刷新同步
首先来看setInterval的缺陷,使用setInterval()创建的定时器确保了定时器代码规则地插入队列中。这个问题在于:如果定时器代码在代码再次添加到队列之前还没完成执行,结果就会导致定时器代码连续运行好几次。而之间没有间隔。不过幸运的是:javascript引擎足够聪明,能够避免这个问题。当且仅当没有该定时器的如何代码实例时,才会将定时器代码添加到队列中。这确保了定时器代码加入队列中最小的时间间隔为指定时间。
这种重复定时器的规则有两个问题:1.某些间隔会被跳过 2.多个定时器的代码执行时间可能会比预期小。
用setTimeout来实现setInterval
思路是使用递归函数,不断地去执行setTimeout从而达到setInterval的效果,看代码
function mySetInterval(fn, millisec){
function interval(){
setTimeout(interval, millisec);
fn();
}
setTimeout(interval, millisec)
}
这个mySetInterval函数有一个叫做interval的内部函数,它通过setTimeout来自动被调用,在interval中有一个闭包,调用了回调函数并通过setTimeout再次调用了interval。
我们再增加一个额外的参数用来标明代码执行的次数
function mySetInterval(fn, millisec,count){
function interval(){
if(typeof count===‘undefined’||count-->0){
setTimeout(interval, millisec);
try{
fn()
}catch(e){
count = 0;
throw e.toString();
}
}
}
setTimeout(interval, millisec)
}
<div id="mypic">onload</div>
<script>
var obj = new Image();
obj.src = "";
obj.onload = function(){
alert('图片的宽度为:'+obj.width);
document.getElementById('#mypic').innerHTML = ""
}
</script>
// 方法二
var obj = new Image();
obj.src = "";
obj.onreadystatechange = function(){
if(this.readystate == "complate"){
alert();
document.getElementById("mypic").innerHTML = ""
}
}
// while循环
function sleep(ms) {
var start = Date.now(),
expire = start + ms;
while (Date.now < expire);
console.log('.');
return
}
//promise
function sleep(ms) {
var temple = new Promise(
(resolve) => {
console.log(111); setTimeout(resolve, ms)
});
return temple
}
sleep(500).then(function () {
//console.log(222)
})
function myPromise(constructor){
let self=this;
self.status="pending" //定义状态改变前的初始状态
self.value=undefined;//定义状态为resolved的时候的状态
self.reason=undefined;//定义状态为rejected的时候的状态
function resolve(value){
//两个==="pending",保证了状态的改变是不可逆的
if(self.status==="pending"){
self.value=value;
self.status="resolved";
}
}
function reject(reason){
//两个==="pending",保证了状态的改变是不可逆的
if(self.status==="pending"){
self.reason=reason;
self.status="rejected";
}
}
//捕获构造异常
try{
constructor(resolve,reject);
}catch(e){
reject(e);
}
}
myPromise.prototype.then=function(onFullfilled,onRejected){
let self=this;
switch(self.status){
case "resolved":
onFullfilled(self.value);
break;
case "rejected":
onRejected(self.reason);
break;
default:
}
}
mozilla内核 (firefox,flock等) -moz
webkit内核(safari,chrome等) -webkit
opera内核(opera浏览器) -o
trident内核(ie浏览器) -ms
① iframe会阻塞主页面的Onload事件;
② 搜索引擎的检索程序无法解读这种页面,不利于SEO;
③ 会影响页面的并行加载。
什么是并行加载?
并行加载:同一时间针对同一域名下的请求。一般情况,iframe和所在页面在同一个域下面,而浏览器的并加载的数量是有限制的。如下图
使用js动态给iframe的src加载页面内容,示例代码如下:
<iframe id="fram"></iframe>
document.getelementbyid("fram").src="a2.html"
相同点
都可以用来表示伪类对象,用来设置对象前的内容
:befor和::before写法是等效的
不同点
:befor是Css2的写法,::before是Css3的写法
:before的兼容性要比::before好 ,不过在H5开发中建议使用::before比较好
加分项
伪类对象要配合content属性一起使用
伪类对象不会出现在DOM中,所以不能通过js来操作,仅仅是在 CSS 渲染层加入
伪类对象的特效通常要使用:hover伪类样式来激活
.test:hover::before { /* 这时animation和transition才生效 */ }
animation是css3动画它由三部分组成。
①关键帧@keyframes:定义了动画在不同阶段的状态,用宝粉笔划分阶段(语法@keyframes 名称{
form to
})
②动画的属性:1.时间函数(animation-timing-function)定义了动画的播放速度曲线,默认是ease(先块慢再快),还可以取值:ease-in,ease-out,linear(匀速)。2.animation-direction:表示动画是否返向播放参数:normal:正序,reserve倒序;3.animtion-delay:延迟,定义动画从什么时候开始播放
③css属性:css不同关键帧下的状态
.list div:first-child{
animation:dropdown 8s linear infinite
}
@keyframes dropdowm{
0&{margin-top:0px}
10%{}
...deng
}
对象的键不能相同
function norepeat(arr){
var obj = {};
var newarr = [];
for(var i = 0;i<arr.length;i++){
if(!obj[arr[i]]){
obj[arr[i]] = 1;
newarr.push(arr[i])
}
}
return newarr
}
console.log(norepeat([1,1,1,1,1,1]))
利用indexof如果检索的结果没有匹配值,则返回 -1.
如果检索的结果匹配到,则返回 1.
function fn1(arr){
var newarr = [];
for(var i = 0; i <arr.length;i++){
if(newarr.indexOf(arr[i]) == -1){
newarr.push(arr[i])
}
}
return newarr;
}
console.log(fn1([1,1,1,2,6,9,9]))
数组排序后相邻去除法
function fn7(arr){
arr.sort();
var newarr = arr[arr[0]];
for(var i = 0 ;i <arr.length;i++){
if(arr[i] !== newarr[newarr.length - 1]){
newarr.push(arr[i])
}
}
return newarr
}
fun.bind(this,arg1,arg2,…)
bind()方法会创建一个新的函数,称为绑定函数,fun方法在this环境下调用
该方法可传入两个参数,第一个参数作为this,第二个及以后的参数则作为函数的参数调用
var obj = {
init: 1,
add: function(a, b) {
return a + b + this.init;
}
}
obj.add(1, 2); // 4
var plus = obj.add;
plus(3, 4); // NaN,因为 this.init 不存在,这里的 this 指向 window/global
plus.call(obj, 3, 4) // 8
plus.apply(obj, [3, 4]); // 8, apply 和 call 的区别就是第二个参数为数组
plus.bind(obj, 3, 4); // 返回一个函数,这里就是 bind 和 call/apply 的区别之一,bind 的时候不会立即执行
plus.bind(obj, 3, 4)(); // 8
手写个源码
Function.prototype.mybind = function(target){
// target改变返回函数的this指向
var self = this;
var args = [].slice.call(arguments,1)
var temp = function(){};
var f = function(){
var _args = [].slice.call(arguments,0)
return self.apply(this instanceof temp ? this : target || window,args.concat(_args))
}
temp.prototype = self.prototype;
f.prototype = new temp();
return f;
}
var obj = {
init: 1,
add: function (a, b) {
return a + b + this.init
}
}
var g = obj.add(1, 2);
console.log(g);//4
var plus = obj.add;
var j = plus(1, 2);
console.log(j)//NaN 因为直接调用此时this指向window init为undefiened
plus.call(obj, 3, 4)
var h = plus.mybind(obj, 1, 4)();
console.log(h)
200:请求成功
301:永久重定向,新url会在定位响应头给出,浏览器会自动连接到新的url。
302:临时重定向,希望本次访问使用新的url。客户端请求的资源已经被临时的放置到了一个新的地址,新的地址出现在URL的响应头的Location中。通常,浏览器遇到该响应,会将访问的地址加入到历史记录中,然后重新去请求新地址。
303:请求对应的资源存在着另一个URL,使用get定向获取请求资源。
403:没有访问权限。
404:请求的资源找不到。
503:服务器端无法响应。
跨域访问资源,那些东西属于资源?
JS文件,css文件,jpg,png等允许被跨域请求,src属性的资源都是可以被跨域请求的,href资源大部分都是可以被跨域请求的。
哪些资源算跨域请求?
1.都断接口的数据
2.其他域的cookie
3.其他域的缓存
什么是其他的域?
页面本身:有协议(http/https),域名,端口
要请求的数据:https://www.baidu.com:80
协议域名端口号有任意一个不一样就算跨域。
跨域这个行为,发生在哪里?
即使跨域了(协议域名端口号不相同了)也可以发送资源,服务器可以正常处理接收返回数据,但是浏览器接收后会发现当前页面的域和请求的域不一样,就会判定为跨域,我们的代码在等待结果,但是因为浏览器判定跨域了,所以不会把结果传递给我们。
跨域的处理方式:
①Jsonp:利用了标签不收同源策略限制。
jsonp发送的时候会带上一个callback,结果返回的不是json,是callback的名+(+ json +)
jsonp跨域只能使用get方法,如果我们设置的是post方法,jq会自动转为get
问:是不是只能使用get?设置的post都是转为get
答:不是。jq会先判断是否同源,如果是同源设置的是什么就是什么,如果不是同源,无论设置的什么都改成get。
<script>
$.ajax({
url:"xxx",
type:"get",
dataType:'jsonp',
success:function(){
console.log(data)
}
})
</script>
jsonp的原理
<script>
// jsonp原理:
// 1.判断请求与当前页面的域,是否同源,如果同源则发送正常的ajax。
// 2.如果不同源,生成一个script标签
// 3.生成一个随机的callback名字,创建一个名为这个的方法。
// 4.设置script标签的src,设置为要请求的接口。
// 5.将callback作为参数拼接在后面
// 后端部分:
// 1、后端接收到请求后,准备返回的数据
// 2.后端拼接到数据,将要返回的数据用callback的值和括号包裹起来。将内容返回
// 3.浏览器接收到内容,当做js代码来执行,我们就接受到了
// 封装如下
var $ = {
ajax:function(options){
var url = options.url;
var type = options.type;
var dataType = options.dataType;
// 判断是否同源(协议,域名,端口号)
// 首先获取目标url的域
var targetProtocol = "";//协议
var targetHost = '';//包含域名和端口
// 如果url不带http那么访问的就是相对路径,相对路径同源的
if(url.indexof("http://") == 0 || url.indexof("https:// == 0")){
var targetUrl = new URL(url);
targetProtocol = targetUrl.protocol;
targetHost = targetUrl.host;
}else{
targetProtocol.location.protocol;
targetHost = location.host;
}
// 首先判断是否jsonp
if(dataType == "jsonp"){
if(location.protocol == targetProtocol && location.host == targetHost){
// 同源,jsonp当做普通ajax做请求
}else{
// 不同源
// 随机生成一个callback
var callback = "cb" + Math.floor(Math.random() * 1000000)
// 给window上添加一个方法
Window[callback] = options.success;
// console.log(Window.callback)
// 生成script标签
var script = document.createElement('script');
if(url.indexof("?") > 0){
// 表示已经有参数了
}else{
// 表示没有参数
script.src = url + "?callback" + callback
}
script.id = callback;
document.head.appendChild(script);
}
}
}
}
</script>
②CORS(跨域资源共享):允许当前域的资源被其他域的资源请求访问。
也就是后端设置:access-Control-Origin
属性支持跨域
当使用XMLHttpRequest发送请求时,浏览器如果发现违反了同源策略就会自动加上一个请求头:origin,后端在接
受到请求后确定响应后会在Response Headers中加入一个属性:Access-Control-Allow-Origin,值就是发起请求的源地址,浏览器得到响应会进行判断Access-Control-Allow-Origin的值是否和当前的地址相同,只有匹配成
功后才进行响应处理。
现代浏览器中和移动端都支持CORS,IE下需要8+
③服务器跨域,服务器中转代理
iframe(只能显示不能控制)
前端向本地服务器发送请求,本地服务器代替前端再向服务器接口发送请求进行服务器间通信,本地服务器是个
中转站的角色,再将响应的数据返回给前端。
1.静态资源压缩合并(JS/css代码压缩合并)
2.静态资源缓存
3.使用CDN加载资源
4.css放在前面,js放在后面,懒加载
5.减少DOM操作
cookie webStorage(localStorage sessionStorage)
①LocalStorage
保存的数据长期存在(特点:持久),下一次访问该网站的时候,网页可以直接读取以前保存的数据。仅在客户端使用,不和服务器进行通信。
可以作为浏览器本地缓存方案。用来提升网页首屏渲染速度(根据第一次返回,将一些不变得信息直接存储在本地)
存入数据:locoalStorage.setItem("key","value");
读取数据:locoalStorage.getItem("key");
<body>
<div id="name"></div>
<div id="gender"></div>
<script>
var name = localStorage.getItem("name");
var gender = localStorage.getItem("gender");
document.getElementById("name").innerHTML = name;
document.getElementById("gender").innerHTML = gender;
</script>
</body>
△因为他的特点是持久,所以用它来存储一些内容稳定的资源,比如图片内容丰富的电商网站存储图片字符串。
②sessionStorage
sessionStorage保存的数据用于浏览器的一次会话,会话结束的时候(窗口关闭的时候),数据被清空;他的特点:即使是相同域名下的两个页面,只要他们不在同一个浏览器窗口中打开,他们的sessionStorage就无法共享;localStorage在所有窗口中是共享的,cookie也是在所有同源窗口中共享。除了保存期限的长短不同,SessionStorge的属性方法和localStorage的完全一样。
sassionStorage的特点:会话级别的浏览器存储,5M左右,仅在客户端使用,不和服务端进行通信,接口封装良好。
所以sessionStorage可以有效的对表单信息进行维护,比如刷新的时候,表单信息不丢失。只适用于当前会话,存储生命周期和他同步的当前级别的会话,当你开启新会话的时候,他也需要相应的更新或释放。
sessionStorage 和localStorage的区别:
同:都保存在浏览器端且都遵循同源策略。
异:生命周期与作用域不同。
作用域:localStorage只要在相同的协议域名端口号下,就能够读取或者修改同一份localStorage数据。sessionStorage比localStorage严苛,还必须在同一个窗口下。
生命周期:localStorage是持久化的本地存储,存储在里面的数据除非手动删除否则不会过期。sessionStorage是临时性的本地存储,会话级别存储,会话结束存储内容释放。
webStorage
键值对形式进行存储,只能存储字符串,想要得到对象就要对字符串进行解析,只能存储少量的简单数据。
④IndexedDB:
低级Api,客户端存储大量结构化数据。引用索引实现对数据的高能搜索,是一个运行在浏览器上的非关系型的数据库。没有存储上限,不仅可以存储字符串,还可以存储二进制数据。
特点:键值对存储。异步(localStorage的操作是同步的)异步是为了防止大量数据读写,拖慢网页。支持事务(只要有一步失败,整个失误就取消,数据库回滚到事务发生之前的状态,不存在只写一部分数据的情况)。同源限制,每一个数据库对应创建他的域名,网页只能访问同源下的数据库。存储空间大。支持二进制存储。
他的操作是请求响应模式:
建立打开 IndexedDB ----window.indexedDB.open("testDB")
这条指令并不会返回一个 DB 对象的句柄,我们得到的是一个 IDBOpenDBRequest 对象,
而我们希望得到的 DB 对象在其 result 属性中 除了 result,IDBOpenDBRequest 接口定义了几个重要属性:
onerror: 请求失败的回调函数句柄 onsuccess:请求成功的回调函数句柄 onupgradeneeded:请求数据库版本
变化句柄
<script>
function openDB(name) {
var request = window.indexedDB.open(name); //建立打开
IndexedDB request.onerror = function (e) {
console.log("open indexdb error");
};
request.onsuccess = function (e) {
myDB.db = e.target.result; //这是一个 IDBDatabase 对象,这就是 IndexedDB 对象
console.log(myDB.db); //此处就可以获取到 db 实例 };
}
var myDB = { name: "testDB", version: "1", db: null };
openDB(myDB.name);
</script>
总结:
Web Storage 是 HTML5 专门为浏览器存储而提供的数据存储机制,不与 服务端发生通信 IndexedDB 用于客户端存储大量结构化数据
请求方面:
1.GET会被浏览器主动缓存,POST不会,除非手动设置。
2.GET请求只能进行URL编码,POST支持多重编码方式。
3.GET请求参数会被完整保存在浏览器历史记录里,POST中的参数不会保存。
4.GET比POST更不安全,因为参数直接暴露在URL中。GET参数通过URL传递,POST放在request body中
加载过程:
DNS解析域名为IP地址,向这个IP的机器发送HTTP请求,服务器收到,处理并返回HTTP请求,浏览器得到返回内容。
渲染过程:
根据HTML结构生成DOM树,CSS生成CSSOM树,将DOM和CSSOM整合生成RenderTree,根据渲染数开始展示,遇到的时候会执行并阻止渲染
1.TCP传输控制协议,UDP用户数据报协议
2.TCP面向连接,UDP无连接
3,TCP提供可靠服务,传送的数据无差错不丢失不重复按序到达;UDP尽最大努力交付,不保证可靠。
4.TCP面向字节流,UDP面向报文。
5.TCP是点到点的,UDP是一对一,一对多,多对一
6.TCP首部开销20字节,UDP8字节
7.TCP是全双工可靠信道,UDP是不可靠信道
超文本传输协议,是TCP/IP协议的一个应用层协议,用于定义WEB浏览器和WEB服务器之间交换数据的过程。
HTTPS是在HTTP的基础上加了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间通信加密。http是明文传输,https是具有安全性的ssl加密传输协议。http的连接很简单,是无状态的,HTTPS是由SSL+HTTP协议构建的可进行加密传输,身份验证的网络协议,比http安全。
浏览器会把HTML解析成DOM,把css解析成cssOM,然后他们合并产生rendertree,然后我们会知道所有节点的样式,计算他们在页面上的大小和位置,最后把节点绘制到页面上。
回流:就是渲染树中部分或全部元素的尺寸,结构,或某些属性发生变化的时候,浏览器重新渲染部分或全部文档。页面首次渲染,浏览器窗口大小发生改变,元素尺寸或位置发生改变,元素内容变化(文字数量或图片大小等等),元素字体大小变化,添加或者删除可见的DOM元素。
重绘:当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
避免频繁的样式操作,最好一次性重写style,或者一次性更改class,避免频繁操作dom,对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
(1)定义一个规范,该请求方法服务端如何理解:业务数据在哪,是否需要一些特殊的请求头,什么时候应该使用这个方法。
(2)服务器端通过代码读取到请求方法,然后根据规范的约束进行处理。
(3)客户端(浏览器)请求服务器的时候用ajax请求服务器,按照规范的要求传递数据。
为C/S两端提供了实时交互通信的能力,允许服务器主动发送信息给客户端,是一种区别于HTTP的全新双向数据流协议,基于TCP。
浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过TCP连接传输数据。
可实现实时数据、订阅推送,在WebSocket规范提出之前,采用轮询,设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动,浪费流量和服务器资源