笔记

文章目录

一.浏览器

1.http和https的区别

(1)https协议需要ca证书,费用较高。
(2)http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
(3)http协议的端口为80,https的端口为443。FTP的端口是21
(4)http的连接很简单,是无状态的;https协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
https协议的主要作用是:建立一个信息安全通道,来确保数组的传输,确保网站的真实性。
https的SSL加密是在传输层实现的。

2.TCP的三次握手和四次挥手

三次握手

img

​ 客户端和服务端都需要知道各自可收发,因此需要三次握手。

​ 从图片可以得到三次握手可以简化为:C发起请求连接S确认,S也发起连接C确认
每次握手的作用:
​ 第一次握手:S只可以确认自己可以接受C发送的报文段。(C向S发送SYN包)
​ 第二次握手:C可以确认S收到了自己发送的报文段,并且可以确认自己可以接受S发送的报文段。(S向C发送SYN和ACK包)
​ 第三次握手:S可以确认C收到了自己发送的报文段。(C向S发送ACK包)

四次挥手

img

每次挥手的作用

第一次挥手:客户端进程发出连接释放报文,并且停止发送数据。(C向S发送FIN包)

第二次挥手:服务器收到连接释放报文,发出确认报文。(S向C发送ACK包)

第三次挥手:服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,由于在半关闭状态,服务器很可能又发送了一些数据,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。(S向C发送FIN和ACK包)

第四次挥手:客户端收到服务器的连接释放报文后,必须发出确认。(C向S发送ACK包)

思考:那么为什么是4次挥手呢?

为了确保数据能够完成传输。

3.TCP和UDP的区别

TCP和UDP协议是TCP/IP协议的核心。
(1)TCP是面向连接的,UDP是无连接的,即发送数据前不需要先建立连接。
(2)TCP提供可靠的服务。通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付。 并且因为TCP可靠,面向连接,不会丢失数据,因此适合大数据量的交换。
(3)TCP是面向字节流,UDP面向报文,并且网络出现拥塞不会使得发送速率降低(因此会出现丢包,对实时的应用比如IP电话和视频会议等)。
(4)TCP只能是1对1的,UDP支持1对1,1对多。
(5)TCP的首部较大为20字节,而UDP只有8字节。
(6)TCP是面向连接的可靠性传输,而UDP是不可靠的。

TCP在IP协议上添加了序号机制、确认机制、超时重传机制等,保证了传输的可靠性,不会出现丢包和乱序

TCPUDP
是否连接面向连接无连接
传输可靠性可靠传输,使用流量控制和拥塞控制不可靠传输,不使用流量控制和拥塞控制
速度
连接对象个数只能是一对一通信支持一对一,一对多,多对一和多对多交互通信
传输方式面向字节流面向报文
首部开销首部最小20字节,最大60字节首部开销小,仅8字节
适用场景适用于要求可靠传输的应用,例如文件传输、电子邮件、远程登录适用于实时应用(IP电话、视频会议、直播、音乐等)
4.cookie和session的区别

(1)cookie数据存放在客户的浏览器上,session数据放在服务器上。
(2)cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,
考虑到安全应当使用session。
(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用COOKIE。
(4)单个cookie保存的数据不能超过4KB,很多浏览器都限制一个站点最多保存20个cookie。

5.cookie、sessionStorage、localStorage的区别

​ HTML5中的Web Storage的目的是克服由cookie所带来的一些限制,Web Storage又分为两种:sessionStorage和localStorage。

  • sessionStorage将数据保存在session对象中。所谓session,是指用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间。session对象可以用来保存在这段时间内所要求保存的任何数据。
  • localStorage将数据保存在客户端本地的硬件设备(通常指硬盘,也可以是其他硬件设备)中,即使浏览器被关闭了,该数据仍然存在,下次打开浏览器访问网站时仍然可以继续使用。
    这两者的区别在于,sessionStorage为临时保存,而localStorage为永久保存。
6.常见http状态码
状态码响应类别原因短语
1XX信息性状态码(Informational)服务器正在处理请求
2XX成功状态码(Success)请求已正常处理完毕
3XX重定向状态码(Redirection)需要进行额外操作以完成请求
4XX客户端错误状态码(Client Error)客户端原因导致服务器无法处理请求
5XX服务器错误状态码(Server Error)服务器原因导致处理请求出错

(1)100 Continue 继续。客户端应继续其请求
(2)101 Switching Protocols 切换协议。服务器根据客户端的请求切换协议。只能切换到更高级的协议,例如,切换到HTTP的新版本协议
(3)200 OK 请求成功。一般用于GET与POST请求
(4)201 Created 已创建。成功请求并创建了新的资源
(5)202 Accepted 已接受。已经接受请求,但未处理完成
(6)203 Non-Authoritative Information 非授权信息。请求成功。但返回的meta信息不在原始的服务器,而是一个副本
(7)204 No Content 无内容。服务器成功处理,但未返回内容。在未更新网页的情况下,可确保浏览器继续显示当前文档
(8)205 Reset Content 重置内容。服务器处理成功,用户终端(例如:浏览器)应重置文档视图。可通过此返回码清除浏览器的表单域
(9)206 Partial Content 部分内容。服务器成功处理了部分GET请求
(10)300 Multiple Choices 多种选择。请求的资源可包括多个位置,相应可返回一个资源特征与地址的列表用于用户终端(例如:浏览器)选择
(11)301 Moved Permanently 永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
(12)302 Found 临时移动。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
(13)303 See Other 查看其它地址。与301类似。使用GET和POST请求查看
(14)304 Not Modified 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。客户端通常会缓存访问过的资源,通过提供一个头信息指出客户端希望只返回在指定日期之后修改的资源
(15)305 Use Proxy 使用代理。所请求的资源必须通过代理访问
(16)306 Unused 已经被废弃的HTTP状态码
(17)307 Temporary Redirect 临时重定向。与302类似。使用POST请求重定向
(18)400 Bad Request 客户端请求的语法错误,服务器无法理解
(19)401 Unauthorized 请求要求用户的身份认证
(20)402 Payment Required 保留,将来使用
(21)403 Forbidden 服务器理解请求客户端的请求,但是拒绝执行此请求
(22)404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面
(23)405 Method Not Allowed 客户端请求中的方法被禁止
(24)406 Not Acceptable 服务器无法根据客户端请求的内容特性完成请求
(25)407 Proxy Authentication Required 请求要求代理的身份认证,与401类似,但请求者应当使用代理进行授权
(26)408 Request Time-out 服务器等待客户端发送的请求时间过长,超时
(27)409 Conflict 服务器完成客户端的PUT请求是可能返回此代码,服务器处理请求时发生了冲突
(28)410 Gone 客户端请求的资源已经不存在。410不同于404,如果资源以前有现在被永久删除了可使用410代码,网站设计人员可通过301代码指定资源的新位置
(29)411 Length Required 服务器无法处理客户端发送的不带Content-Length的请求信息
(30)412 Precondition Failed 客户端请求信息的先决条件错误
(31)413 Request Entity Too Large 由于请求的实体过大,服务器无法处理,因此拒绝请求。为防止客户端的连续请求,服务器可能会关闭连接。如果只是服务器暂时无法处理,则会包含一个Retry-After的响应信息
(32)414 Request-URI Too Large 请求的URI过长(URI通常为网址),服务器无法处理
(33)415 Unsupported Media Type 服务器无法处理请求附带的媒体格式
(34)416 Requested range not satisfiable 客户端请求的范围无效
(35)417 Expectation Failed 服务器无法满足Expect的请求头信息
(36)500 Internal Server Error 服务器内部错误,无法完成请求
(37)501 Not Implemented 服务器不支持请求的功能,无法完成请求
(38)502 Bad Gateway 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
(39)503 Service Unavailable 由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中
(40)504 Gateway Time-out 充当网关或代理的服务器,未及时从远端服务器获取请求
(41)505 HTTP Version not supported 服务器不支持请求的HTTP协议的版本,无法完成处理

7.浏览器缓存

缓存分为两种:强缓存和协商缓存,根据响应的header内容来决定。

  • 强缓存:
    用户发送的请求,直接从客户端缓存中获取,不发送请求到服务器,不与服务器发生交互行为。
  • 协商缓存: 用户发送请求,发送到服务器之后,由服务器判定是否从缓存中获取资源。
    两者共同点:客户端获取的数据最后都是从客户端的缓存中取得。
    两者区别:从名字就可以看出,强缓存不与服务器发生交互,而协商缓存则需要需服务器发生交互。
获取资源形式状态码发送请求到服务器
强缓存从缓存取200 (from cache)否,直接从缓存取
协商缓存从缓存取304 (not modified)是,通过服务器来告知缓存是否可用

强缓存相关字段有expires,cache-control。如果cache-control与expires同时存在的话,cache-control的优先级高于expires。

协商缓存相关字段有Last-Modified/If-Modified-Since,Etag/If-None-Match

8.常见的http头部

可以将http首部分为通用首部,请求首部,响应首部,实体首部
(1)通用首部表示一些通用信息,比如date表示报文创建时间。
(2)请求首部就是请求报文中独有的,如cookie,和缓存相关的如if-Modified-Since。
(3)响应首部就是响应报文中独有的,如set-cookie,和重定向相关的location。
(4)实体首部用来描述实体部分,如allow用来描述可执行的请求方法,content-type描述主题类型,content-Encoding描述主体的编码方式。

cookie 、 Cache-Control(是否使用缓存) 、Referer(服务器访问的前一个页面)

connection(链接类型) 、 Expires(过期时间)

常用的 HTTP 请求方法:GET、POST、DELETE、PUT、OPTIONS、HEAD

9.get和post区别

(1)传送方式:get通过地址栏传输,post通过报文传输。
(2)get请求在url中传递的参数是有长度限制的,而post没有。
(3)get不安全,因为参数直接暴露在url中,所以不能用来传递敏感信息。
(4)get请求只能进行url编码,而post支持多种编码方式。
(5)get请求参数会被完整保留在浏览历史记录里,而post中的参数不会被保留。
(6)get产生一个TCP数据包;post产生两个TCP数据包。对于get方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于post,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。

10.浏览器从输入URL到页面生成发生的过程

(1)输入地址,发送至DNS服务器,获取相应的域名和服务器IP地址

(2)与服务器建立TCP连接

(3)浏览器向服务器发送请求

(4)服务器响应请求,并发送响应数据

(5)浏览器下载数据,并解析文件,渲染页面,呈现页面

​ 浏览器先解析HTML文件,然后遍历文档节点,生成DOM树,再解析CSS文件,生成CSSOM规则树,如果有JS文件,先解析JS文件,再生成Render树,即渲染树

11.http版本及区别

1991年  HTTP/0.9 仅支持GET请求,不支持请求头

1996年  HTTP/1.0 默认短连接(一次请求建议一次TCP连接,请求完就断开),支持GET、POST、 HEAD请求

1999年  HTTP/1.1 默认长连接(一次TCP连接可以多次请求);支持PUT、DELETE、PATCH等六种请求

增加host头,支持虚拟主机;支持断点续传功能

2015年  HTTP/2.0 多路复用,降低开销(一次TCP连接可以处理多个请求);允许同时通过单一的HTTP/2连接发送多重请求-响应信息。改善了:在http1.1中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制(连接数量),超过限制会被阻塞。

服务器主动推送(相关资源一个请求全部推送);

解析基于二进制,解析错误少,更高效(HTTP/1.X解析基于文本);

报头压缩,降低开销。

12.前端优化

从三个大的方向入手:A 资源缓存 、B 资源的合并压缩、C 浏览器的加载、解析、渲染机制

A 资源缓存

(1) 将静态资源部署在CDN;

(2)利用HTTP缓存机制:利用Headers的Cache-control参数 —— 减少http请求次数

B 资源的合并压缩

  • JS和CSS的处理:合并是减少JS文件数 —— 减少HTTP请求;压缩是极大减小文件的体积。一般而言会分类为:公共代码+页面响应代码+第三方代码,这样可以对JS或者CSS实现按需加载

  • 图片的处理:
    (1)使用webP格式
    (2)使用iconfont替换img
    (3)CSS Sprite合并图片
    (4)使用base64直接把图片编码写入css中

C 浏览器加载、解析、渲染机制

  • 将CSS引入的link写在<head>

  • 引用外部的JS文件一般写在<script>底部,避免加载JS会阻塞HTML的解析。

  • 代码层面尽量减少重绘,避免重排:
    (1)尽量通过class处理样式切换
    (2)需要多次重排的元素可以设置position为absolute或fixed,使元素尽量脱离文档流

当浏览器解析到 <script>标签,有如下三种情况:

  • 如果标签内是内嵌到HTML中的JS代码 —— 直接执行

  • 如果是外链JS文件,且该文件未下载完 —— HTML解析过程被阻塞直到JS文件下载完毕 —— JS执行 —— HTML继续解析

  • 如果是外链JS文件,且文件已下载完毕 —— 直接执行JS代码,且并不阻塞HTML解析

13.XSS和CSRF网络攻击的区别和防范

XSS:Cross Site Scripting,跨站脚本攻击
CSRF:cross-site request forgery,跨站请求伪造

区别:

(1)CSRF需要登陆后操作,XSS不需要。

(2)CSRF是请求页面api来实现非法操作,XSS是向当前页面植入js脚本来修改页面内容。

防范:

  • XSS
    (1)为cookie设置httpOnly属性;
    (2)对输入、输出结果进行过滤和必要的转义;
    (3)尽量使用post,使用get方式时对路径长度进行限制。
  • CSRF
    (1)使用验证码;
    (2)检查请求的referer是否正确;
    (3)在请求地址中添加 token 并验证
14.OSI七层模型

“物链网传会表应”

从下至上:物理层、数据链路层、网络层、传输层、会话层、表示层、应用层

15.TCP/IP层次模型

从下至上:数据链路层、网络层、传输层、应用层

TCP在传输层

IP在网络层

HTTP在应用层

16.WebSocket的实现

​ websocket 是HTML5的协议,支持持久连续 (http不支持持久性链接);

​ websocket 基于http协议,2个属性upgrade设置为websocket ,connection设置为Upgrade

二.HTML

1.iframe

定义:iframe元素会创建包含另一个文档的内联框架
提示:可以将提示文字放在之间,来提示某些不支持iframe的浏览器

缺点:

​ 会阻塞主页面的onload事件

​ 搜索引擎无法解读这种页面,不利于SEO

​ iframe和主页面共享连接池,而浏览器对相同区域有限制所以会影响性能。

2.Doctype作用?严格模式和混杂模式区分

​ Doctype声明于文档最前面,告诉浏览器以何种方式来渲染页面,这里有两种模式,严格模式和混杂模式。
​ 严格模式的排版和JS 运作模式是 以该浏览器支持的最高标准运行。
​ 混杂模式,向后兼容,模拟老式浏览器,防止浏览器无法兼容页面。

3.HTML5和CSS3
  • html5新标签:

    • section 内容区块 article 核心内容 header 区块的头部 footer 底部信息 nav 导航信息 aside:侧边栏
    • 音频和视频标签 audio 和 vedio
    • canvas: 进行图形绘制
  • css3新属性

    transform变形;transform:translate(100px,100px);位移

    transform:scale(0.5.,0.2);缩放

    transform:rotate(30deg);旋转

  • border-radius 圆角设置

4.BFC(块级格式上下文)

触发:

(1)float的值不是none。

(2)position为absolute和fixed

(3)display为 inline-block、table-cell、flex、table-caption或者inline-flex

(4)overflow为auto(滚动条)或hidden

应用:

(1)防止margin重叠,把后面一个元素放在div里,设置overflow:hidden

(2)BFC的区域不会与float box重叠 ,可以完成自适应两列布局

5.webWoker

​ HTML5引入了一个工作线程(webWorker)的概念。它允许开发人员编写能够长时间运行而不被用户所中断的后台程序,去执行事务或者逻辑,并同时保证页面对用户的响应。

​ 简而言之,就是允许JavaScript创建多个线程,但是子线程完全受主线程控制,且不得操作DOM

三.CSS

1.CSS盒模型

(1)W3C标准盒子(content-box):又称内容盒子,是指块元素box-sizing属性为content-box的盒模型。它的width是内容的宽度

(2)IE盒子(border-box):又称怪异盒模型,是指块元素box-sizing属性为border-box的盒模型。它的width是content + padding + border

2.盒子水平垂直居中的实现

需要宽高

(1)设置宽高,设置绝对定位,设置left和top为50%,设置margin-left和margin-top为自身宽高的一半

.box {
    position: absolute;
    left:50%;
    top:50%;
    margin-left:-50px;
    margin-top:-50px;
    width:100px;
    height: 100px;
    background-color: red;
}

(2)设置宽高,设置绝对定位,设置left、right、top、bottom为0,设置margin为auto

.box {
    position: absolute;
    left:0;
    top:0;
    right:0;
    bottom:0;
    margin:auto;
    width:100px;
    height: 100px;
    background-color: green;
}

不需要宽高

(1)transforms 变形(最简单的方法)

设置绝对定位,transform: translate(-50%,-50%) ,top: 50%,left: 50%

.box {
     padding: 20px;
     background: orange;
     color: #fff;
     position: absolute;
     top: 50%;
     left: 50%;
     border-radius: 5px;
     -webkit-transform: translate(-50%, -50%);
     -moz-transform: translate(-50%, -50%);
     transform: translate(-50%, -50%);
}

(2)flex布局,给父元素加CSS属性(子元素有或无宽高都适用)

.box{
    justify-content: center; /*子元素水平居中*/
    align-items: center; /*子元素垂直居中*/
    display: -webkit-flex;
}
3.清除浮动的方法

1.额外标签法

​ 给浮动元素后面加一个块级标签,设置该块级标签clear:both

​ 缺点:会增加额外的标签

​ 2.父元素设置overflow:hidden

​ 缺点:溢出隐藏

​ 3.父元素设置:after伪类

 .clearfix:after {
     content: "";
     display: block;
     height: 0;
     clear: both;
     visibility: hidden;
}

.clearfix {
	*zoom: 1;
}

​ 4.父元素设置双伪类

.clearfix:before,
    .clearfix:after {
    content: "";
    display: table;
}
.clearfix:after {
	clear: both;
}
.clearfix {
	*zoom: 1;
} 
4.弹框的实现

点击弹出框按钮,背景色变为灰色
(1)在原页面基础上添加两个层,一个是弹出层,一个是遮罩层。这两个div先设置display:none让其不显示,然后通过按钮绑定事件实现显示和隐藏。 (XX.style.display = “block”)
(2)设置弹出层的显示大小

width: 200px;
height: 200px;
position:fixed;
top:50%;
left:50%;
transform:translateX(-50%) translateY(-50%);

(3)使用z-index属性设置背景层和弹出层的上下位置,值越大越靠上显示;
(4)设置背景层的透明度

5.左右固定,中间自适应布局

(1)自身浮动法

1.左右分别使用左浮动 float:left和右浮动float:right使其脱离文档流
2.中间的div放在最后占据文档流位置,设置margin-left 和 margin-right

(2)绝对定位法

1.左右设置absolute,父元素设置relative      
2.左边设置top:0px; left:0px;  右边:top:0px; right:0px; 
3.中间的div设置margin-left和margin-right

(3)flex布局

1.父级元素设置: display:flex    
2.中间div设置  flex:1
==center元素一定要放在中间==

(4)圣杯布局(浮动和父margin)

1.三个元素设置position:relative,float: left
2.左右设置magin-left (负值)  
6.Flex布局

Flex容器有两根轴:水平主轴就是x轴(main axis),竖直轴是y轴(cross axis)。

Flex布局有两层,采用flex布局的元素称为flex容器,其子元素则自动成flex item,即项目。

Flex:是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。

( flex-grow:定义项目的放大比例 ; flex-shrink:定义了项目的缩小比例 , flex-basis:定义了在分配多余空间之前,项目占据的主轴空间 )

弹性布局常用属性:

  • display : flex (弹性布局,父级)
  • justify-content (水平对齐,父级)
  • align-items (垂直对齐,父级,不换行无效,用于修改flex-wrap)
  • flex-wrap (换行,父级)
  • align-self (垂直对齐,子级)
  • flex-basis , flex-shrink, flex-grow
7.CSS三大特性

(1)层叠性:后来者居上

(2)继承性:子元素继承父元素的样式,如color、font-,line-height等

​ font:12px/1.5 “Microsoft yahei”;

​ 字体大小为12px,行高为当前字体大小的1.5倍

(3)优先级:继承、通配符选择器 0

​ 标签选择器 1

​ 类和伪类选择器 10

​ id选择器 100

​ 行内样式表 1000

​ !important 无穷大

优先级,权重叠加,无进位问题

8.定位

定位=定位模式+边偏移

​ 定位模式有静态定位(static)、相对定位(reletive)、绝对定位(absolute)、固定定位(fixed)

​ 边偏移是定位的盒子移到的最终位置,有top、bottom、left、right四个属性

(1).静态定位:position:static;浏览器默认的定位方式,按照标准流特性摆放位置,无定位,无边偏移

(2).相对定位:position:relative;相对于自身原来的位置进行定位,占有文档流,即不脱标

(3).绝对定位:position:absolute;不占有文档流,即脱标

​ 注意:“子绝父相”

  • 没有父元素或者父元素没有相对定位或绝对定位或固定定位时,相对于浏览器进行定位
  • 有父元素时,相对于最近的有定位的父元素的位置进行定位

(4).固定定位:position:fixed;

​ 相对于浏览器可视区进行定位,不占有文档流,即脱标,鼠标滚动时,位置不移动

(5).粘性定位:position:sticky;

​ 是相对定位和绝对定位的综合,相对于浏览器可视区进行定位,占有文档流

​ 例:浏览器可视区底部的返回顶部按钮

​ position:sticky;

​ left:50%;将盒子定位到浏览器可视区的中间

​ margin-left:核心块宽度的一半;

定位的拓展:

​ 1.浮动不会压住下面标准流的文字,浮动最初的目的就是设置文字环绕

​ 绝对定位和固定定位会压住下面标准流的文字

​ 2.行内元素设置绝对定位或固定定位,可以直接设置宽高

​ 块级元素设置绝对定位或固定定位,如果不设置宽高,默认为内容的大小

​ 3.脱标的元素不会触发外边距塌陷

​ 浮动、绝对定位、固定定位不会触发外边距合并问题

9.元素的显示与隐藏

(1).display 元素隐藏后不占有原来位置

​ 值为none时,隐藏元素

​ 值为block时,显示元素

(2).visibility 元素隐藏后占有原来位置

​ 值为visible,显示元素

​ 值为none时,隐藏元素

(3).overflow 溢出显示隐藏

​ 值为visible,显示溢出元素

​ 值为hidden,隐藏溢出元素

​ 值为scroll,显示滚动条

​ 值为auto,有溢出时,显示滚动条;没有溢出时,不显示滚动条

10.link和@import的区别

(1)link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。

(2)link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。

(3)link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。

(4)link支持使用Javascript控制DOM去改变样式;而@import不支持。

四.JS

1.数组的方法

(1)join() 原数组不变

把数组转换成字符串,然后给他规定个连接字符,默认的是逗号( ,)

​ 书写格式:join(" "),括号里面写字符串

(2)push()和pop()

push(): 把里面的内容添加到数组末尾,并返回修改后的长度。

pop():移除数组最后一项,返回移除的那个值,减少数组的length。

​ 书写格式:arr.push(" "),括号里面写内容 (“字符串要加引号”),

书写格式:arr.pop( )

(3)shift()和unshift()

shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。

unshift():将参数添加到原数组开头,并返回数组的长度 。

​ 书写格式:arr.shift(" "),括号里面写内容 (“字符串要加引号”)

(4)sort()

sort():将数组里的项从小到大排序

​ 书写格式:arr.sort( )

​ sort()方法比较的是字符串,没有按照数值的大小对数字进行排序,要实现这一点,就必须使用一个排序函数

function sortNumber(a,b)
{
  return a - b
}
arr = [13, 24, 51, 3]; 
console.log(arr.sort());        // [13, 24, 3, 51] 
console.log(arr.sort(sortNumber));     // [3, 13, 24, 51](数组被改变)

(5)reverse()

reverse():反转数组项的顺序。

​ 书写格式:arr.reverse( )

(6)concat() 原数组不变

concat() :将参数添加到原数组中。这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。

​ 书写格式:arr.concat(),括号里面写内容 (“字符串要加引号”)

(7)slice() 原数组不变

slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项,但不包括结束位置的项,即左闭右开

​ 书写格式:arr.slice( 1 , 3 )

(8)splice()

splice():删除、插入和替换。返回的都是删除的值。

删除:指定 2 个参数:要删除的第一项的位置和要删除的项数。

书写格式:arr.splice( 1 , 3 )

插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。

书写格式:arr.splice( 2,0,4,6 )
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。

书写格式:arr.splice( 2,0,4,6 )

var arr = [1,3,5,7,9,11];
var arrRemoved = arr.splice(0,2);
console.log(arr);                //[5, 7, 9, 11]
console.log(arrRemoved);            //[1, 3]
var arrRemoved2 = arr.splice(2,0,4,6);
console.log(arr);                // [5, 7, 4, 6, 9, 11]
console.log(arrRemoved2);           // []
var arrRemoved3 = arr.splice(1,1,2,4);
console.log(arr);                // [5, 2, 4, 4, 6, 9, 11]
console.log(arrRemoved3);           //[7]

(9)indexOf()和lastIndexOf()

indexOf():在数组中搜索元素值并返回其位置。接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头(位置 0)开始向后查找。

​ 书写格式:arr.indexOf( 5 )

lastIndexOf:接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。

书写格式:arr.lastIndexOf( 5,4 )

var arr = [1,3,5,7,7,5,3,1];
console.log(arr.indexOf(5));       //2
console.log(arr.lastIndexOf(5));     //5
console.log(arr.indexOf(5,2));      //2
console.log(arr.lastIndexOf(5,4));   //2
console.log(arr.indexOf("5"));      //-1

(10)forEach()

forEach():对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。参数都是function类型,默认有传参,参数分别为:遍历的数组内容;第对应的数组索引,数组本身。

​ 书写格式:arr.forEach()

(11)map() 原数组不变

map():指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。

​ 书写格式:arr.map()

请注意,该函数有 3 个参数:

  • 项目值
  • 项目索引
  • 数组本身
var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);

function myFunction(value, index, array) {
  return value * 2;
}

当回调函数仅使用 value 参数时,可以省略索引和数组参数

var arr = [1, 2, 3, 4, 5];
var arr2 = arr.map(function(item){
return item*item;
});
console.log(arr2);         //[1, 4, 9, 16, 25]

(12)some()

some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。

书写格式:arr.some()

var arr = [1, 2, 3, 4, 5];
var arr2 = arr.some(function(x) {
return x < 3;
}); 
console.log(arr2);         //true
var arr3 = arr.some(function(x) {
return x < 1;
}); 
console.log(arr3);         // false

(13)every()

every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。

书写格式:arr.every()

(14)filter()

filter():“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。

书写格式:arr.filter()

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arr2 = arr.filter(function(x, index) {
return index % 3 === 0 || x >= 8;
}); 
console.log(arr2);         //[1, 4, 7, 8, 9, 10]
2.数组去重的方法

Methods 1: 思路:定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中。

        function unique(arr) {
            let newArr = [arr[0]];
            for (let i = 1; i < arr.length; i++) {
                let repeat = false;
                for (let j = 0; j < newArr.length; j++) {
                    if (arr[i] === newArr[j]) {
                        repeat = true;
                        break;
                    }else{
                        
                    }
                }
                if (!repeat) {
                    newArr.push(arr[i]);
                }
            }
            return newArr;
        }
 
        console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
        // 结果是[1, 2, 3, 5, 6, 7, 4]

Methods 2: 思路:先将原数组排序,在与相邻的进行比较,如果不同则存入新数组。

        function unique2(arr) {
            var formArr = arr.sort()
            var newArr=[formArr[0]]
            for (let i = 1; i < formArr.length; i++) {
                if (formArr[i]!==formArr[i-1]) {
                    newArr.push(formArr[i])
                }
            }
            return newArr
        }
        console.log(unique2([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
        // 结果是[1, 2, 3,  4,5, 6, 7]

Methods 3: 利用对象属性存在的特性,如果没有该属性则存入新数组。

        function unique3(arr) {
            var obj={}
            var newArr=[]
            for (let i = 0; i < arr.length; i++) {
                if (!obj[arr[i]]) {
                    obj[arr[i]] = 1
                    newArr.push(arr[i])
                }   
            }
            return newArr
        }
        console.log(unique2([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
        // 结果是[1, 2, 3, 5, 6, 7, 4]

Methods 4: 利用数组的indexOf下标属性来查询。

        function unique4(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(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
        // 结果是[1, 2, 3, 5, 6, 7, 4]

Methods 5: 利用数组原型对象上的includes方法。

        function unique5(arr) {
            var newArr = []
            for (var i = 0; i < arr.length; i++) {
                if (!newArr.includes(arr[i])) {
                    newArr.push(arr[i])
                }
            }
            return newArr
        }
        console.log(unique5([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
        // 结果是[1, 2, 3, 5, 6, 7, 4]

Methods 6: 利用数组原型对象上的 filter 和 includes方法。

    function unique6(arr) {
        var newArr = []
        newArr = arr.filter(function (item) {
            return newArr.includes(item) ? '' : newArr.push(item)
        })
        return newArr
    }
    console.log(unique6([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
    // 结果是[1, 2, 3, 5, 6, 7, 4]

Methods 7: 利用数组原型对象上的 forEach 和 includes方法。

          function unique7(arr) {
            let newArr = [];
            arr.forEach(item => {
                return newArr.includes(item) ? '' : newArr.push(item);
            });
            return newArr;
        }
        console.log(unique7([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
        // 结果是[1, 2, 3, 4, 5, 6, 7]

Methods 8: 利用数组原型对象上的 splice 方法。

        function unique8(arr) {
            var i,j,len = arr.length;
            for (i = 0; i < len; i++) {
                for (j = i + 1; j < len; j++) {
                    if (arr[i] == arr[j]) {
                        arr.splice(j, 1);
                        len--;
                        j--;
                    }
                }
            }
            return arr;
        }
        console.log(unique8([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));

Methods 9: 利用数组原型对象上的 lastIndexOf 方法。

        function unique9(arr) {
            var res = [];
            for (var i = 0; i < arr.length; i++) {
                res.lastIndexOf(arr[i]) !== -1 ? '' : res.push(arr[i]);
            }
            return res;
        }
        console.log(unique9([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
        // 结果是[1, 2, 3, 5, 6, 7, 4]

Methods 10: 利用 ES6的set 方法和数组的Array.from方法。

        function unique10(arr) {
            //Set数据结构,它类似于数组,其成员的值都是唯一的
            return Array.from(new Set(arr)); // 利用Array.from将Set结构转换成数组
        }
        console.log(unique10([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
        // 结果是[1, 2, 3, 5, 6, 7, 4]

Methods 11: 利用 ES6的set 方法和扩展运算符。

let arr = [1,2,3,3];
let resultarr = [...new Set(arr)]; 
console.log(resultarr); //[1,2,3]
3.闭包

在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

闭包可以用在许多地方。它的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中,不会随着函数调用结束而销毁。

JS 的闭包包含以下要点:

(1)函数声明的时候,会生成一个独立的作用域

(2)同一作用域的对象可以互相访问

(3)作用域呈层级包含状态,形成作用域链,子作用域的对象可以访问父作用域的对象,反之不能;另外子作用域会使用最近的父作用域的对象

4.跨域及解决方案

​ 跨域,是指浏览器不能执行其他网站的脚本。跨域原理,即是通过各种方式,避开浏览器的安全限制。

造成跨域的原因:

同源策略限制,不同源会造成跨域。以下任意一种情况不同,都是不同源。

同源:协议 域名 端口号全部相同 只要有一个不相同就是非同源策略。

(1)、 通过jsonp跨域

​ 原理:动态创建一个script标签。利用script标签的src属性不受同源策略限制。因为所有的src属性和href属性都不受同源策略限制。可以请求第三方服务器数据内容。

​ 步骤:

  • 去创建一个script标签
  • script的src属性设置接口地址
  • 接口参数,必须要带一个自定义函数名 要不然后台无法返回数据。
  • 通过定义函数名去接收后台返回数据
//去创建一个script标签
var  script = document.createElement("script");
//script的src属性设置接口地址 并带一个callback回调函数名称
script.src = "http://127.0.0.1:8888/index.php?callback=jsonpCallback";
//插入到页面
document.head.appendChild(script);
//通过定义函数名去接收后台返回数据
function jsonpCallback(data){
    //注意  jsonp返回的数据是json对象可以直接使用
    //ajax  取得数据是json字符串需要转换成json对象才可以使用。
}

通过动态创建script,再请求一个带参网址实现跨域通信。

缺点:只能实现get一种请求

(2)、 document.domain + iframe跨域

此方案仅限主域相同,子域不同的跨域应用场景。

实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

// URL http://a.com/foo
var ifr = document.createElement('iframe');
ifr.src = 'http://b.a.com/bar'; 
ifr.onload = function(){
    var ifrdoc = ifr.contentDocument || ifr.contentWindow.document;
    ifrdoc.getElementsById("foo").innerHTML);
};

ifr.style.display = 'none';
document.body.appendChild(ifr);

(3)、 location.hash + iframe
(4)、 window.name + iframe跨域
(5)、 postMessage跨域
(6)、 跨域资源共享(CORS)

原理:服务器设置Access-Control-Allow-OriginHTTP响应头之后,浏览器将会允许跨域请求

限制:浏览器需要支持HTML5,可以支持POST,PUT等方法兼容ie9以上

需要后台设置
Access-Control-Allow-Origin: *              //允许所有域名访问,或者
Access-Control-Allow-Origin: http://a.com   //只允许所有域名访问

(7)、 nginx代理跨域
(8)、 nodejs中间件代理跨域
(9)、 WebSocket协议跨域

5.js数据类型

基本数据类型(值类型):number、string、boolean、null、undefined

引用数据类型:object、array、function、date等

console.log(typeof null); //object
console.log(typeof {}); //object
console.log(typeof []); //object
console.log(typeof NULL);  //undefined
console.log(typeof Object);  //function
console.log(typeof undefined == undefined);  //false

值类型:

  • 占用空间固定,保存在栈中,在当前环境执行结束时销毁
  • 保存和赋值是值的本身
  • 可以使用typeof检测数据类型

引用数据类型:

  • 占用空间不固定,保存在堆中,只有在引用的它的变量不在时,会被垃圾回收机制回收。 (引用变量存储在栈中的是指向堆中的数组或者对象的地址 )
  • 保存与复制的是指向对象的一个指针
  • 使用instanceof检测数据类型
  • 使用new()方法构造出的对象是引用型
6.事件循环机制

​ js是一个单线程,事件循环机制是在执行上下文过程中,对函数的入栈和出栈。执行前函数先入栈,执行完后函数出栈。当遇到异步任务时,会将异步任务放进任务队列里,当所有的同步任务执行完后,才会执行任务队列里的异步任务。异步任务分为宏任务和微任务。

**宏任务(macro-task)**包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。
**微任务(micro-task)**包括:process.nextTick, Promise, Object.observe, MutationObserver 、

执行顺序:函数调用栈清空只剩全局执行上下文,然后开始执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次执行macro-task中的一个任务队列,执行完之后再执行所有的micro-task,就这样一直循环。

当当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行。

微任务队列优先于宏任务队列执行,微任务队列上创建的宏任务会被后添加到当前宏任务队列的尾端,微任务队列中创建的微任务会被添加到微任务队列的尾端。只要微任务队列中还有任务,宏任务队列就只会等待微任务队列执行完毕后再执行。

Promise的回调函数不是传入的,而是使用then来调用的。因此,Promise中定义的函数应该是马上执行的,then才是其回调函数,放入任务队列中。

console.log(1);
setTimeout(function(){console.log(2);}, 0);
console.log(3);
//输出结果:
//1
//3
//2
7.事件防抖

​ 事件触发一次,就会发送一次请求,会有无数次地抖动。

​ 如: 键盘事件:onkeydown,onkeyup,onkeypress,oninput,都是按一次键,触发一次,触发非常频繁。

使用场景:

​ 搜索框(百度搜索框,淘宝,京东等等),每次用户输入内容都需要发一次请求,从后端拿到关键字对应的内容,特别是输入汉字时:

​ 我们希望用户输入完成汉字时再触发(发送请求)。

​ 但是,实际情况是:当用户输入一个字母时,就会触发一次事件(发送一次请求)。

防抖:在用户连续触发事件过程中,不能执行代码。

事件防抖的关键在:用户有停顿时,才执行代码(调用函数),没有停顿时,不执行代码。

let i = 0;
let myTimer = null;
 
window.onscroll = function(){	
	if(myTimer!=null){
		window.clearTimeout(myTimer);
	}
	//重新启动定时器
	myTimer = setTimeout(()=>{
		console.log(i++);
		myTimer =null;
	},200);
	
}
 
function $(id){
	return document.getElementById(id);
}
8.函数节流

​ 节流的意思是:不要调用太频繁,如每隔200ms调用一次。

使用场景:

​ 在页面无数次的滚动时(就会触发无数次的onscroll),但是我希望触发(调用函数)时不要那么频繁。

函数节流的关键在于:用户停顿不停顿都会触发,但触发的频率(调用函数)没有原始事件那么多。

let i = 0;
let myTimer = null;
window.onscroll = function(){	
	if(myTimer!=null){
		return;
	}
	myTimer = setTimeout(()=>{
		console.log(i++);
		myTimer =null;
	},1000);
}
9.深拷贝和浅拷贝

深拷贝是对值类型进行拷贝,拷贝的是值,一个对象值的改变不会影响另一个对象。

浅拷贝是对引用数据类型的拷贝,拷贝的是地址,一个对象值的改变会影响另一个对象。

10.字符串方法

(1)charAt() 返回某个位置的字符。
(2)concat() 将一个或多个字符串拼接起来,返回拼接后的字符串。该方法不会修改原字符串。
(3)==slice()、substr()、substring()==不会修改字符串本身的值,而是将结果返回。有两个参数时:slice和substring返回下标从第一个参数开始到第二个参数-1结束的子串。substr返回下标从第一个参数开始长度为第二个参数的子串
(4)split() 将字符串分割并返回一个数组
(5)trim() 删除字符串前置以及后缀的所有空格并将结果保存在新的字符串中返回
(6)join将一个数组拼接成字符串并返回该字符串,元素之间以join接收的参数作为分割符(默认是",")

11.轮播图的实现

主要思想:

(1)容器的css布局。

(2)每一次轮播通过偏移量left实现,手动轮播的按钮绑定每一次偏移量增加还是减少一张照片宽度的偏移量。

(3)自动轮播,通过setInterval()方法实现定时器,执行下一张的点击函数。

(4)鼠标控制轮播的暂停和继续。通过onmouseover为暂停,onmouseout为继续。

具体实现:

(1)先创建一个div,设置其宽高,overflow:hidden,并设置其position:relative。

(2)然后创建一个装图片的div,宽度为所有图片的总宽度,且设置其position:absolute,并设置浮动让所有图片处于一行中。

(3)为实现无缝滚动,在首尾分别添加一张过渡图片。

(4)添加两个按钮,通过改变偏移量left实现手动轮播。

(5)添加一个定时器使其向同一个方向自动轮播。

(6)鼠标移入时清除定时器,移出时在定时播放。

(7)为提高用户体验,可以在下面添加一排小圆点,利用闭包使用户可以直接通过点击小圆点切换图片。

12.垃圾回收机制和内存泄漏

不再用到的内存,没有及时释放,就叫做内存泄漏。

解决内存的泄露,垃圾回收机制会定期(周期性)找出那些不再用到的内存(变量),然后释放其内存。

现在各大浏览器通常采用的垃圾回收机制有两种方法:标记清除引用计数

常见的引起内存泄漏的原因:

(1)全局变量引起的内存泄漏

function leaks(){  
    leak = 'xxxxxx';//leak 成为一个全局变量,不会被回收
}

(2)闭包引起的内存泄漏

var leaks = (function(){  
    var leak = 'xxxxxx';// 被闭包所引用,不会被回收
    return function(){
        console.log(leak);
    }
})()

(3)dom清空或删除时,事件未清除导致的内存泄漏

<div id="container">  
</div>

$('#container').bind('click', function(){
    console.log('click');
}).remove();
// zepto 和原生 js下,#container dom 元素,还在内存里jquery 的 empty和 remove会帮助开发者避免这个问题
<div id="container">  
</div>

$('#container').bind('click', function(){
    console.log('click');
}).off('click').remove();
//把事件清除了,即可从内存中移除

(4)子元素存在引用引起的内存泄漏

13.arguments
 // arguments是js函数中的一个内置对象,当不知道函数参数个数的时候可以使用。

 function getSum() {

	console.log(arguments); //里面存储了所有传递过来的实参

	console.log(arguments.length);

}

 getSum(1,2,3);

 getSum(1,2,3,4,5,6);

 // arguments是一个伪数组

 // 伪数组:并不是真正意义上的数组

 // 1.具有数组的length属性

 // 2.按照索引的方式进行存储

 // 3.它没有真正数组的方法,如pop()、push()等
14.new关键字

new在执行时会做四件事情:

​ (1).在内存中创建一个新的空对象

​ (2).让this指向这个新的对象

​ (3).执行构造函数里的代码,给这个新对象添加属性和方法

​ (4).返回这个新对象(所以构造函数里不需要return)

15.预解析

js引擎运行js分为两步:预解析和代码执行

​ 1.预解析:变量预解析(变量提升)、函数预解析(函数提升)

​ (1)变量提升:就是把所有的变量声明提升到当前作用域最前面,不提升赋值操作

​ (2)函数提升:就是把所有的函数声明提升到当前作用域的最前面,不调用函数

​ 2.代码执行:按顺序从上往下依次执行

16.纯函数

​ 一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数。只要是同样的输入,必定得到同样的输出。

纯函数是函数式编程的概念,必须遵守以下一些约束:

(1)不得改写参数
(2)不能调用系统 I/O 的API
(3)不能调用Date.now()或者Math.random()等不纯的方法,因为每次会得到不一样的结果

17.原型链

原型链:当实例调用某一个属性时,先在本身找,如果没有找到,就到它的原型对象上逐级往上找(__ proto__),直到找到Object.prototype,如果还找不到则原路返回(constructor),告诉它方法或属性未定义。

只有函数有prototype属性,对象都有__ proto __。

实例的__ proto __属性指向的是它的构造函数的原型对象。
在这里插入图片描述

总结:原型链就是在访问一个对象属性的时候,如果自身没有找到的情况下会去它的原型对象中查找,如果还没有,会去它的原型对象的原型对象中查找,如此循环直到顶层的Object对象的原型对象(是个null,Object.prototype.__ proto __===null)为止的这么个机制。

五.ES6

1.let、const、var的区别

​ const 声明只读常量,一旦声明,常量值不能修改(只针对常量,数组和对象的值可修改,不能修改的是内存地址)
​ const必须有初始化,不能只定义不赋值
let和var 的区别:
​ let不存在变量提升,同一作用域下不能重复定义同一名称,有严格的作用域(var 函数作用域,let块级作用域)

let暂时性死区:

​ 块级作用域内存在let命令 , 形成了封闭作用域。 凡是在声明之前就使用这些变量,就会报错。

2.set和map的区别

应用场景:Set用于数据重组,Map用于数据储存

Set: 
(1)成员不能重复
(2)只有键值没有键名,类似数组
(3)可以遍历,方法有add, delete,has
Map:
(1)本质上是健值对的集合,类似集合
(2)可以遍历,可以跟各种数据格式转换

3.forEach、for in、for of三者区别

forEach更多的用来遍历数组
for in 一般常用来遍历对象或json
for of数组对象都可以遍历,遍历对象需要通过Object.keys()
for in循环出的是key,for of循环出的是value

4.理解 async/await以及对Generator的优势

​ async await 是用来解决异步的,async函数是Generator函数的语法糖
​ 使用关键字async来表示,在函数内部使用 await 来表示异步
​ async函数返回一个 Promise 对象,可以使用then方法添加回调函数
​ 当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句
async较Generator的优势:
(1)内置执行器。Generator 函数的执行必须依靠执行器,而 Aysnc 函数自带执行器,调用方式跟普通函数的调用一样
(2)更好的语义。async 和 await 相较于 * 和 yield 更加语义化  
(3)更广的适用性。yield命令后面只能是 Thunk 函数或 Promise对象,async函数的await后面可以是Promise也可以是原始类型的值
(4)返回值是 Promise。async 函数返回的是 Promise 对象,比Generator函数返回的Iterator对象方便,可以直接使用 then() 方法进行调用

5.使用class 手写一个promise
//创建一个Promise的类
  class Promise{
    constructor(executer){//构造函数constructor里面是个执行器
      this.status = 'pending';//默认的状态 pending
      this.value = undefined//成功的值默认undefined
      this.reason = undefined//失败的值默认undefined
      //状态只有在pending时候才能改变
      let resolveFn = value =>{
        //判断只有等待时才能resolve成功
        if(this.status == pending){
          this.status = 'resolve';
          this.value = value;
        }
      }
      //判断只有等待时才能reject失败
      let rejectFn = reason =>{
        if(this.status == pending){
          this.status = 'reject';
          this.reason = reason;
        }
      }    
      try{
        //把resolve和reject两个函数传给执行器executer
        executer(resolve,reject);
      }catch(e){
        reject(e);//失败的话进catch
      }
    }
    then(onFufilled,onReject){
      //如果状态成功调用onFufilled
      if(this.status = 'resolve'){
        onFufilled(this.value);
      }
      //如果状态失败调用onReject
      if(this.status = 'reject'){
        onReject(this.reason);
      }
    }
  }
6.Promise 中reject 和 catch 处理上有什么区别

reject 是用来抛出异常,catch 是用来处理异常
reject 是 Promise 的方法,而 catch 是 Promise 实例的方法
reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch
网络异常(比如断网),会直接进入catch而不会进入then的第二个回调

7.promise有几种状态,什么时候会进入catch?

三个状态:
pending、fulfilled、rejected
两个过程:
padding -> fulfilled、padding -> rejected

当pending为rejectd时,会进入catch

8.箭头函数和普通函数的区别
  1. 箭头函数没有prototype(原型)
  2. 箭头函数的this在定义的时候继承自外层第一个普通函数的this。
  3. 如果箭头函数外层没有普通函数,严格模式和非严格模式下它的this都会指向window(全局对象)
  4. 箭头函数本身的this指向不能改变,但可以修改它要继承的对象的this。
  5. 箭头函数的this指向全局,使用arguments会报未声明的错误。
  6. 箭头函数的this指向普通函数时,它的argumens继承于该普通函数
  7. 使用new调用箭头函数会报错,因为箭头函数没有constructor
  8. 箭头函数不支持new.target
  9. 箭头函数不支持重命名函数参数,普通函数的函数参数支持重命名
  10. 箭头函数相对于普通函数语法更简洁优雅

​ 要分为这几个方面的区别: 1、this指向 2、arguments 3、箭头函数没有原型 4、箭头函数不能使用new来构造 5、不允许重命名参数 6、语法更优雅 7、 不支持new.target

六.AJAX

1.ajax的基本步骤

简述 AJAX:AJAX即“Asynchronous Javascript And XML”(异步 JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

AJAX 基本步骤:

//1.创建 XMLHttpRequest 对象
var ajax = new XMLHttpRequest();
//2.规定请求的类型、URL 以及是否异步处理请求。
ajax.open('GET',url,true);
//3.发送信息至服务器时内容编码类型
//ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); 
//4.发送请求
ajax.send(null);  
//5.接受服务器响应数据
ajax.onreadystatechange = function () {
    if (obj.readyState == 4 && (obj.status == 200 || obj.status == 304)) { 
    }
};

Ajax优点:

1.最大的一点是页面无刷新,用户的体验非常好。

2.使用异步方式与服务器通信,具有更加迅速的响应能力。

3.可以把以前一些服务器负担的工作转嫁到客户端,利用客户端闲置的能力来处理,减轻服务器和带宽的负担,节约空间和宽带租用成本。并且减轻服务器的负担,ajax的原则是“按需取数据”,可以最大程度的减少冗余请求,和响应对服务器造成的负担。

4.基于标准化的并被广泛支持的技术,不需要下载插件或者小程序。

AJAX局限性:

  1. AJAX 不支持浏览器 back 按钮。
  2. 安全问题 AJAX 暴露了与服务器交互的细节。
  3. 对搜索引擎的支持比较弱。不会执行你的 JS 脚本,只会操作你的网页源代码;
  4. 跨域请求有一定限制。解决方式:jsonp;
2.XMLHttpRequest对象的常用方法和属性

​ XmlHttpRequest使您可以使用JavaScript向服务器提出请求并处理响应,而不阻塞用户。通过XMLHttpRequest对象,Web开发人员可以在页面加载以后进行页面的局部更新。

方法:

  • open()(String method,String url,boolean asynch,String username,String password)
  • send(content)
  • setRequestHeader(String header,String value)
  • getAllResponseHeaders()
  • getResponseHeader(String header)
  • abort()

常用的方法就是黑色粗体的前三个

  • open():该方法创建http请求
    • 第一个参数是指定提交方式(post、get)
    • 第二个参数是指定要提交的地址是哪
    • 第三个参数是指定是异步还是同步(true表示异步,false表示同步)
    • 第四和第五参数在http认证的时候会用到。是可选的
  • setRequestHeader(String header,String value):设置消息头(使用post方式才会使用到,get方法并不需要调用该方法)
    • xmlhttp.setRequestHeader(“Content-type”,“application/x-www-form-urlencoded”);
  • send(content):发送请求给服务器
    • 如果是get方式,并不需要填写参数,或填写null
    • 如果是post方式,把要提交的参数写上去

属性:

  • onreadystatechange:请求状态改变的事件触发器(readyState变化时会调用此方法),一般用于指定回调函数

  • readyState:请求状态readyState一改变,回调函数被调用,它有5个状态

    • 0:未初始化
    • 1:正在加载,open方法成功调用以后
    • 2:已加载,服务器已经应答客户端的请求
    • 3:交互中,Http头信息已经接收,响应数据尚未接收。
    • 4:完成,数据接收完成
  • responseText:服务器返回的文本内容

  • responseXML:服务器返回的兼容DOM的XML内容

  • status:服务器返回的状态码,200对应ok,400对应not found

  • statusText:服务器返回状态码的文本信息

3.ajax几种请求方式?他们的优缺点?

常用的post,get,delete。不常用copy、head、link等等。

###代码上的区别
 1:get通过url传递参数
 2:post设置请求头  规定请求数据类型
###使用上的区别
 1:post比get安全
 (因为post参数在请求体中。get参数在url上面)
 2:get传输速度比post快 根据传参决定的。
 (post通过请求体传参,后台通过数据流接收。速度稍微慢一些。而get通过url传参可以直接获取)
 3:post传输文件大理论没有限制  get传输文件小大概7-8k ie4k左右
 4:get获取数据	post上传数据
 (上传的数据比较多  而且上传数据都是重要数据。所以不论在安全性还是数据量级 post是最好的选择)
4.json字符串转换集json对象、json对象转换json字符串
//1.字符串转对象
JSON.parse(json)
eval('(' + jsonstr + ')')   
//2.对象转字符串
JSON.stringify(json)
5.前后端数据交互

从前端向后台传递参数方法:

  1. 通过表单传递参数

    (1)前端部分,在前端jsp页面设置form表单,确定需要传递的参数name让用户输入,通过点击按钮后submit()提交到后台

    <form id="loginform" name="loginform" action="<%=path %>/login" method="post">
                        <div class="form-group mg-t20">
                            <i class="icon-user icon_font"></i>
                            <input type="text" class="login_input" id="sfzh" name="sfzh" placeholder="请输入用户名" />
                        </div>
                        <div class="form-group mg-t20">
                            <i class="icon-lock icon_font"></i>
                            <input type="password" class="login_input" id="pwd"  name="pwd" placeholder="请输入密码" />
                        </div>
                        <div class="checkbox mg-b25">
                            <label>
                                <!--  <input type="checkbox" />记住密码 -->
                            </label>
                            <span style="color: red;" id="error">
    							<%
    			                String message = (String)request.getAttribute("message");
    						  	if(StringUtils.isNotBlank(message)){
    						  	%><%=message %><%
    						  	}
    			  	            %>
    			  	        </span>
                        </div>
                        <button id="login" type="submit" style="submit" class="login_btn">登 录</button>
                   </form>
    

    (2)后台对前端请求的反应,接收数据,处理数据以及返回数据。

    @RequestMapping(method=RequestMethod.POST)
    	public String dologin(String sfzh, String pwd, RedirectAttributes redirectAttributes){
    		
    		User query = new User();
    		query.setUserAccount(sfzh);
    		
    		HttpSession session = HttpSessionUtil.getHttpSession();
    		
    		List<User> userlist = userService.select(query);
    
  2. 通过ajax传递参数(有post和get写法)

(1)ajax是如何将前端数据传到后台的

function leftmenu(parentid, parentpath,moduleindex){
		var leftcontent="";
		$.ajax({
	 		type: "POST",
			url : "<%=path%>/resource/usermenus",
			data : {parentid:parentid,parentpath:parentpath},
			success : function(data){
				// 处理head menu是否有页面要打开
				leftcontent= template('_menu2tmpl',data);
				$('.nav').html(leftcontent);
				addclick();
				//临时点击显示菜单
				if($('.index-left-warp').width()==0){
					$(".index-left-show").hide();
					$(".index-left-warp").animate({width:"200px"},250);
					timer=setTimeout(function(){
						tabsResize();
					},500);
				};
				
				$(".nav").accordion({
			        //accordion: true,
			        speed: 500,
				    closedSign: '<img src="<%=path%>/images/menu_close.png"/>',
					openedSign: '<img src="<%=path%>/images/menu_open.png"/>'
				});
			}
		});
	}

$.ajax({

​ type: “POST”,//请求方式

​ url : “<%=path%>/resource/usermenus”,//参数url,要把参数传到什么地方

​ data : {parentid:parentid,parentpath:parentpath},//传递什么数据

​ success : function(data){//sucess表示,当数据返回成功后要怎么做,返回的数据存储在data

(2)后台对前端请求的反应,接收数据

@ResponseBody
	@RequestMapping(value = "usermenus")
	public Map<String, Object> usermenus(String parentid, String parentpath) {
		UserDetail user = HttpSessionUtil.getSessionUser();
		String appadmin = Config.getInstance().getCustomValue("app.admin");
		List<Resource> list = null;
		if(user.getUserAccount().equals(appadmin)){
			// 系统内置管理员 默认获取全部授权
			list = resourceservice.queryAllMenuCascade(parentpath);
		}else{
			list = resourceservice.queryUserMenuCascade(user.getId(), parentpath);
		}
		// 初始化根节点
		Resource root= new Resource();
		root.setId(parentid);
		
		Collections.sort(list, new Comparator<Object>() {
			
			public int compare(Object o1, Object o2) {
 
				Resource resource1 = (Resource) o1;
				Resource resource2 = (Resource) o2;
 
				if (resource1.getSort() > resource2.getSort()) {
					return 1;
				}
				if (resource1.getSort() < resource2.getSort()) {
					return -1;
				}
				
				//如果返回0则认为前者与后者相等
				return 0;
			}
		});
 
		// 组装Tree
		return RecDHTree(root,list);
	}

(3)再看看前端接收到后端返回的数据是如何处理的

function leftmenu(parentid, parentpath,moduleindex){
		var leftcontent="";
		$.ajax({
	 		type: "POST",
			url : "<%=path%>/resource/usermenus",
			data : {parentid:parentid,parentpath:parentpath},
			success : function(data){
				// 处理head menu是否有页面要打开
				leftcontent= template('_menu2tmpl',data);
				$('.nav').html(leftcontent);
				addclick();
				//临时点击显示菜单
				if($('.index-left-warp').width()==0){
					$(".index-left-show").hide();
					$(".index-left-warp").animate({width:"200px"},250);
					timer=setTimeout(function(){
						tabsResize();
					},500);
				};
				
				$(".nav").accordion({
			        //accordion: true,
			        speed: 500,
				    closedSign: '<img src="<%=path%>/images/menu_close.png"/>',
					openedSign: '<img src="<%=path%>/images/menu_open.png"/>'
				});
			}
		});
	}
6.后台管理系统权限

​ 后台管理系统的菜单的做成“活的”,即,菜单不能是纯粹的静态的,而应该是根据后端返回来的数据,来显示菜单的。

​ 前端登录(给后端发送用户名和密码),后端验证成功后,会根据登录的用户,给前端返回来菜单数据,比如:

[
    {
        "id":"001",
        "title":"菜单01",
        "url":"menu01.html"
    },
    {
        "id":"002",
        "title":"菜单02",
        "url":"menu02.html"
    },
    {
        "id":"003",
        "title":"菜单04",
        "url":"menu04.html"
    }
]

前端只需要把它循环一下,显示在页面上就行。

7.页面跳转

(1)onclick跳转

设置window的location.href属性

  • onclick="window.location.href='URL'" // 覆盖当前页
  • onclick="location='URL'" // 覆盖当前页

调用window的open方法

  • onclick="window.open('URL','_blank');" // 在新窗口打开
  • onclick="window.open('URL','_self');" // 覆盖当前页

(2)a标签跳转

  • <a href="URL" target="_blank">Preface</a> // 在新窗口打开
  • <a href="URL" target="_self">Preface</a> // 覆盖当前页,target属性默认为_self,此处可省略
8.ajax请求总共有多少种CALLBACK

Ajax请求总共有八种Callback
      onSuccess
      onFailure
      onUninitialized
      onLoading
      onLoaded
      onInteractive
      onComplete
      onException

七.VUE

1.MVM和MVVM的理解

MVVM 是 Model-View-ViewModel 的缩写。
Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
View 代表UI 组件,它负责将数据模型转化成UI 展现出来。
ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

在这里插入图片描述

​ MVC是Model-View- Controller的简写。即模型-视图-控制器。M和V指的意思和MVVM中的M和V意思一样。C即Controller指的是页面业务逻辑。==使用MVC的目的就是将M和V的代码分离。====MVC是单向通信。==也就是View跟Model,必须通过Controller来承上启下。

​ MVC和MVVM的区别并不是VM完全取代了C,只是在MVC的基础上增加了一层VM,只不过是弱化了C的概念,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。也就是说MVVM实现的是业务逻辑组件的重用,使开发更高效,结构更清晰,增加代码的复用性。

2.面向对象

任何事物皆对象,js是面向过程到面向对象的一个过渡,面向对象可以让逻辑代码更加清晰。

面向对象有三大特性:封装、继承、多态

3.Vue的生命周期

beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed 这几个钩子函数,创建=>挂载=>更新=>销毁

​ 钩子函数,其实和回调是一个概念,当系统执行到某处时,检查是否有hook,有则回调。说的更直白一点,每个组件都有属性,方法和事件。所有的生命周期都归于事件,在某个时刻自动执行。

第一次页面加载会触发beforeCreate, created, beforeMount, mounted 。

DOM 渲染在 mounted 中就已经完成。

4.Vue父子组件的通信

(1).父组件与子组件传值
父组件传给子组件:子组件通过props方法接受数据;
子组件传给父组件:$emit方法传递参数
(2).非父子组件间的数据传递,兄弟组件传值
eventBus,就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。项目比较小时,用这个比较合适。(虽然也有不少人推荐直接用VUEX,具体来说看需求咯。技术只是手段,目的达到才是王道。)

八.操作系统

1.进程和线程的区别

(1)进程是资源分配和调度的一个独立单元,而线程是CPU调度的基本单元

(2)同一个进程中可以包括多个线程,并且线程共享整个进程的资源(寄存器、堆栈、上下文),一个进行至少包括一个线程。

(3)进程的创建调用fork或者vfork,而线程的创建调用pthread_create,进程结束后它拥有的所有线程都将销毁,而线程的结束不会影响同个进程中的其他线程的结束

(4)线程是轻两级的进程,它的创建和销毁所需要的时间比进程小很多,所有操作系统中的执行功能都是创建线程去完成的

(5)线程中执行时一般都要进行同步和互斥,因为他们共享同一进程的所有资源

(6)线程有自己的私有属性TCB,线程id,寄存器、硬件上下文,而进程也有自己的私有属性进程控制块PCB,这些私有属性是不被共享的,用来标示一个进程或一个线程的标志

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。

​ 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。

​ 线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。 但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

2.进程间的通信方式

管道,消息队列,共享内存,信号量

3.死锁?死锁产生的原因?死锁的必要条件?怎么处理死锁?

(1)相互等待资源而产生的一种僵持状态,如果没有外力的干预将一直持续这个状态

(2)系统资源不足、相互竞争资源、请求资源顺序不当

(3)互斥、不可抢占、循环等待、请求与保持

(4)因为互斥是不可改变的,所以只能破坏其他三个条件中的一个来解除死锁,方法:剥夺资源、杀死其中一个线程

九.Linux

1.常用指令
ls          显示文件或目录

     -l           列出文件详细信息l(list)

     -a          列出当前目录下所有文件及目录,包括隐藏的a(all)

mkdir         创建目录

     -p           创建目录,若无父目录,则创建p(parent)

cd               切换目录

touch          创建空文件

echo            创建带有内容的文件。

cat              查看文件内容

cp                拷贝

mv               移动或重命名

rm               删除文件

     -r            递归删除,可删除子目录及文件

     -f            强制删除

find              在文件系统中搜索某文件

wc                统计文本中行数、字数、字符数

grep             在文本文件中查找某个字符串

rmdir           删除空目录

tree             树形结构显示目录,需要安装tree包

pwd              显示当前目录

ln                  创建链接文件

more、less  分页显示文本文件内容

head、tail    显示文件头、尾内容

ctrl+alt+F1  命令行全屏模式

十.Bootstrap框架

1、Bootstrap是哪家公司研发的?

Twitter

2、什么是Bootstrap?以及为什么要使用Bootstrap?

Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。Bootstrap 是基于 HTML、CSS、JAVASCRIPT 的。

Bootstrap具有移动设备优先、浏览器支持良好、容易上手、响应式设计等优点,所以Bootstrap被广泛应用。

3、使用Bootstrap时,要声明的文档类型是什么?以及为什么要这样声明?

使用Bootstrap时,需要使用 HTML5 文档类型(Doctype)。

因为Bootstrap 使用了一些 HTML5 元素和 CSS 属性,如果在 Bootstrap 创建的网页开头不使用 HTML5 的文档类型(Doctype),可能会面临一些浏览器显示不一致的问题,甚至可能面临一些特定情境下的不一致,以致于代码不能通过 W3C 标准的验证。

4、如果需要制作响应式图像,需要在标签上面增加什么?

class=“img-responsive”

5、什么是Bootstrap网格系统(Grid System)?

Bootstrap 包含了一个响应式的、移动设备优先的、不固定的网格系统,可以随着设备或视口大小的增加而适当地扩展到 12 列。它包含了用于简单的布局选项的预定义类,也包含了用于生成更多语义布局的功能强大的混合类。

响应式网格系统随着屏幕或视口(viewport)尺寸的增加,系统会自动分为最多12列。

6、Bootstrap 网格系统(Grid System)的工作原理?

(1)行必须放置在 .container class 内,以便获得适当的对齐(alignment)和内边距(padding)。

(2)使用行来创建列的水平组。

(3)内容应该放置在列内,且唯有列可以是行的直接子元素。

(4)预定义的网格类,比如 .row.col-xs-4,可用于快速创建网格布局。LESS 混合类可用于更多语义布局。

(5)列通过内边距(padding)来创建列内容之间的间隙。该内边距是通过 .rows 上的外边距(margin)取负,表示第一列和最后一列的行偏移。

(6)网格系统是通过指定您想要横跨的十二个可用的列来创建的。例如,要创建三个相等的列,则使用三个 .col-xs-4

7、对于各类尺寸的设备,Bootstrap设置的class前缀分别是什么?

超小设备手机(<768px):.col-xs-

小型设备平板电脑(>=768px):.col-sm-

中型设备台式电脑(>=992px):.col-md-

大型设备台式电脑(>=1200px):.col-lg-

8、Bootstrap 网格系统列与列之间的间隙宽度是多少?

间隙宽度为30px(一个列的每边分别是15px)。

9、如果需要在一个标题的旁边创建副标题,可以怎样操作?

在元素两旁添加,或者添加.small的class。

10、如果想给段落添加强调文本,可以怎样操作?添加class=“lead”
11、用Bootstrap,如何设置文字的对齐方式?

class=“text-center” 设置居中文本

class=“text-right” 设置向右对齐文本

class=“text-left” 设置向左对齐文本

12、Bootstrap如何设置响应式表格?

增加class=“table-responsive”

13、使用Bootstrap创建垂直表单的基本步骤?

(1)向父元素添加role=“form”;

(2)把标签和控件放在一个带有class="form-group"的

中,这是获取最佳间距所必需的;

(3)向所有的文本元素、、添加class=“form-control”。

14、使用Bootstrap创建水平表单的基本步骤?

(1)向父元素添加class=“form-horizontal”;

(2)把标签和控件放在一个带有class="form-group"的

中;

(3)向标签添加class=“control-label”。

15、使用Bootstrap如何创建表单控件的帮助文本?

增加class="help-block"的span标签或p标签。

16、使用Bootstrap激活或禁用按钮要如何操作?

激活按钮:给按钮增加.active的class

禁用按钮:给按钮增加disabled="disabled"的属性

17、Bootstrap有哪些关于的class?

(1).img-rounded 为图片添加圆角

(2).img-circle 将图片变为圆形

(3).img-thumbnail 缩略图功能

(4).img-responsive 图片响应式 (将很好地扩展到父元素)

18、Bootstrap中有关元素浮动及清除浮动的class?

(1)class=“pull-left” 元素浮动到左边

(2)class=“pull-right” 元素浮动到右边

(3)class=“clearfix” 清除浮动

19、除了屏幕阅读器外,其他设备上隐藏元素的class?

class=“sr-only”

20、Bootstrap如何制作下拉菜单?

(1)将下拉菜单包裹在class="dropdown"的

中;

(2)在触发下拉菜单的按钮中添加:class=“btn dropdown-toggle” id=“dropdownMenu1” data-toggle=“dropdown”

(3)在包裹下拉菜单的ul中添加:class=“dropdown-menu” role=“menu” aria-labelledby=“dropdownMenu1”

(4)在下拉菜单的列表项中添加:role=“presentation”。其中,下拉菜单的标题要添加class=“dropdown-header”,选项部分要添加tabindex="-1"。

21、Bootstrap如何制作按钮组?以及水平按钮组和垂直按钮组的优先级?

(1)用class="btn-group"的

去包裹按钮组;class="btn-group-vertical"可设置垂直按钮组。

(2)btn-group的优先级高于btn-group-vertical的优先级。

22、Bootstrap如何设置按钮的下拉菜单?

在一个 .btn-group 中放置按钮和下拉菜单即可。

23、Bootstrap中的输入框组如何制作?

(1)把前缀或者后缀元素放在一个带有class="input-group"中的

中;

(2)在该

内,在class="input-group-addon"的 里面放置额外的内容;

(3)把放在元素的前面或后面。

24、Bootstrap中的导航都有哪些?

(1)导航元素:有class="nav nav-tabs"的标签页导航,还有class="nav nav-pills"的胶囊式标签页导航;

(2)导航栏:class=“navbar navbar-default” role=“navigation”;

(3)面包屑导航:class=“breadcrumb”

25、Bootstrap中设置分页的class

默认的分页:class=“pagination”

默认的翻页:class=“pager”

26、Bootstrap中显示标签的class?

class=“label”

27、Bootstrap中如何制作徽章?
<span class="badge"></span>
28、Bootstrap中超大屏幕的作用是什么?

设置class="jumbotron"可以制作超大屏幕,该组件可以增加标题的大小并增加更多的外边距。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值