前端面试HTML部分(二)
- Label的作用是什么?是怎么用的?
label标签来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。
<label for="Name">Number:</label>
<input type=“text“name="Name" id="Name"/>
<label>Date:<input type="text" name="B"/></label>
- HTML5的form如何关闭自动完成功能?
- 1、在IE的Internet选项菜单里的内容–自动完成里面设置
- 2、设置Form的autocomplete为"on"或者"off"来开启或者关闭自动完成功能
- 3、设置输入框的autocomplete为"on"或者"off"来开启或者关闭该输入框的自动完成功能
打开自动完成功能的Form<br>
<form name="form1" autocomplete="on">
打开自动完成功能的输入框
<input type="text" autocomplete="on" name="txtOff1"><br>
关闭自动完成功能的输入框
<input type="text" autocomplete="off" name="txtOn1"><br>
<input type="submit" value="提交"><br>
</form>
关闭自动完成功能的Form<br>
<form name="form1" autocomplete="off">
打开自动完成功能的输入框
<input type="text" autocomplete="on" name="txtOff1"><br>
关闭自动完成功能的输入框
<input type="text" autocomplete="off" name="txtOn1"><br>
<input type="submit" value="提交"><br>
</form>
给不想要提示的 form 或某个 input 设置为 autocomplete=off。
- 如何实现浏览器内多个标签页之间的通信? (阿里)
WebSocket、SharedWorker;
也可以调用localstorge、cookies等本地存储方式;
**方法一:**
localstorge另一个浏览上下文里被添加、修改或删除时,它都会触发一个事件,我们通过监听事件,控制它的值来进行页面信息通信;
页面一代码:
<input id="name">
<input type="button" id="btn" value="提交">
<script type="text/javascript">
$(function(){
$("#btn").click(function(){
var name=$("#name").val();
localStorage.setItem("name", name);
});
});
</script>
页面2代码:
<script type="text/javascript">
$(function(){
window.addEventListener("storage", function(event){
console.log(event.key + "=" + event.newValue);
});
});
</script>
**方法二:**
使用cookie+setInterval,将要传递的信息存储在cookie中,每隔一定时间读取cookie信息,即可随时获取要传递的信息。
页面1代码:
<input id="name">
<input type="button" id="btn" value="提交">
<script type="text/javascript">
$(function(){
$("#btn").click(function(){
var name=$("#name").val();
document.cookie="name="+name;
});
});
</script>
页面2代码:
<script type="text/javascript">
$(function(){
function getCookie(key) {
return JSON.parse("{\"" + document.cookie.replace(/;\s+/gim,"\",\"").replace(/=/gim, "\":\"") + "\"}")[key];
}
setInterval(function(){
console.log("name=" + getCookie("name"));
}, 10000);
});
</script>
注意quirks:Safari 在无痕模式下设置localstorge值时会抛出 QuotaExceededError 的异常;
- webSocket如何兼容低浏览器?(阿里)
Adobe Flash Socket 、
ActiveX HTMLFile (IE) 、
基于 multipart 编码发送 XHR 、
基于长轮询的 XHR
- 页面可见性(Page Visibility API) 可以有哪些用途?
页面可见性: 就是对于用户来说,页面是显示还是隐藏, 所谓显示的页面,就是我们正在看的页面;隐藏的页面,就是我们没有看的页面。 因为,我们一次可以打开好多标签页面来回切换着,始终只有一个页面在我们眼前,其他页面就是隐藏的,还有一种就是…,(把浏览器最小化,所有的页面就都不可见了)。
通过 visibilityState 的值检测页面当前是否可见,以及打开网页的时间等;
在页面被切换到其他后台进程的时候,自动暂停音乐或视频的播放;
document.addEventListener("visibilitychange", function(){
if(document.hidden){
document.title ="hidden";
}else {
document.title = "visibile";
}
})
- 如何在页面上实现一个圆形的可点击区域?
**1、map+area或者svg**
<img src="t.jpg" width="1366" height="768" border="0" usemap="#Map" />
<map name="Map" id="Map">
<area shape="circle" coords="821,289,68" href="www.baidu.com" target="_blank" />
</map>
**2、border-radius**
<style>
.disc{
width:100px;
height:100px;
background-color:dimgray;
border-radius: 50%;
cursor: pointer;
position: absolute;
left:50px;
top:50px;
line-height: 100px;
text-align: center;
color: white;
}
</style>
<div class="disc">智学无忧</div>
**3、纯js实现 需要求一个点在不在圆上简单算法、获取鼠标坐标等等**
示例:
<div id="demo"></div>
<script>
var demo = document.getElementById('demo');
demo.onclick = function(e){
//获取正方形的中心
let left = this.getBoundingClientRect().left
+ this.offsetWidth / 2;
let top = this.getBoundingClientRect().top
+ this.offsetHeight / 2;
//每次鼠标点击的坐标点
let x1 = e.clientX;
let y1 = e.clientY;
//根据两点间距离公式求出鼠标点击的位置距离圆心的距离
//有可能是负数,因此加上绝对值
let distance = Math.abs(Math.sqrt(Math.pow(x1-left, 2)
+ Math.pow(y1 - top, 2)));
//如果两点间距离大于规定的半径距离则不触发事件
if(distance > 100){
console.log('在这个圆内');
}
}
</script>
- 实现不使用 border 画出1px高的线,在不同浏览器的标准模式与怪异模式下都能保持一致的效果。
<div style="height:1px;overflow:hidden;background:red"></div>
- 网页验证码是干嘛的,是为了解决什么安全问题。
作用:
区分用户是计算机还是人的公共全自动程序。可以防止恶意破解密码、刷票、论坛灌水
有效防止黑客对某一个特定注册用户用特定程序暴力破解方式进行不断的登陆尝试。
PS:验证码的原理是服务器端随机生成验证码字符串,保存在内存中,并写入图片,发送给浏览器端显示,浏览器端输入验证码图片上字符,然后提交服务器端,提交的字符和服务器端保存的该字符比较是否一致,一致就继续,否则返回提示。
- title与h1的区别、b与strong的区别、i与em的区别?
**title与h1的区别**
定义:
title是网站标题,
h1是文章主题
作用:
title概括网站信息,可以直接告诉搜索引擎和用户这 个网站是关于什么主题和内容的,是显示在网页Tab栏里的;
h1突出文章主题,面对用户,更突出其视觉效果,指向页面主体信息,是显示在网页中的。(一个html里最好只有一个h1,在SEO中,搜索引擎也非常重视H1)
**b与strong的区别**
定义:
b(bold)是实体标签,用来给文字加粗,
strong是逻辑标签,作用是加强字符语气。
区别:
b标签只是加粗的样式,没有实际含义,常用来表达无强调或着重意味的粗体文字,比如文章摘要中的关键词、 评测文章中的产品名称、文章的导言;
strong表示标签内字符重要,用以强调,其默认格式是加粗,但是可以通 过CSS添加样式,使用别的样式强调。
建议:为了符合CSS3的规范,b应尽量少用而改用strong
**i与em的区别**
定义:
i(italic)是实体标签,用来使字符倾斜,
em(emphasis)是逻辑标签,作用是强调文本内容
区别:
i标签只是斜体的样式,没有实际含义,常用来表达无强调或着重意味的斜体,比如生物学名、术语、外来语;
em表示标签内字符重要,用以强调,其默认格式是斜体,但是可以通过CSS添加样式。
建议:为了符合CSS3的规 范,i应尽量少用而改用em
- 简述一下src与href的区别
src用于替换当前元素;href用于在当前文档和引用资源之间确立联系。
src是source的缩写,指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置
href是Hypertext Reference的缩写,指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接
- Quirks模式是什么?它和Standards模式有什么区别?
在写程序时我们也会经常遇到这样的问题,如何保证原来的接口不变,又提供更强大的功能,尤其是新功能不兼容旧功能时。IE6以前的页面大家都不会去写DTD,所以IE6就假定 如果写了DTD,就意味着这个页面将采用对CSS支持更好的布局,而如果没有,则采用兼容之前的布局方式。这就是Quirks模式(怪癖模式,诡异模式,怪异模式)。
区别:总体会有布局、样式解析和脚本执行三个方面的区别。
a. 盒模型:在W3C标准中,如果设置一个元素的宽度和高度,指的是元素内容的宽度和高度,而在Quirks 模式下,IE的宽度和高度还包含了padding和border。
b. 设置行内元素的高宽:在Standards模式下,给等行内元素设置wdith和height都不会生效,而在quirks模式下,则会生效。
c. 设置百分比的高度:在standards模式下,一个元素的高度是由其包含的内容来决定的,如果父元素没有设置百分比的高度,子元素设置一个百分比的高度是无效的用
d. 设置水平居中:使用margin:0 auto在standards模式下可以使元素水平居中,但在quirks模式下却会失效。
- 请阐述table的缺点
a. 太深的嵌套,比如table>tr>td>h3,会导致搜索引擎读取困难,而且,最直接的损失就是大大增加了冗余代码量。
b. 灵活性差,比如要将tr设置border等属性,是不行的,得通过td
c. 代码臃肿,当在table中套用table的时候,阅读代码会显得异常混乱
d. 混乱的colspan与rowspan,用来布局时,频繁使用他们会造成整个文档顺序混乱。
e. 不够语义
(后期有更好的题会持续更新~~)
优化方面
- html5哪些操作可以SEO优化?
头部代码
1、标题标签(title标签)
在HTML5中标题标签依然存在,其仍然具有不可替代的作用;不过我们看到还有更多的可供搜索引擎识别的代码,我们将改代码的等级微降。
2、元标签(meta标签)
字符集编码声明标签
该标签原本就是搜索引擎必看且首先要看的标签,其他属性都省略唯独留下charset属性能看到google公司用心良苦。
网页描述标签
该标签虽然没有什么提示,但是该区域的内容将会在SERP显示,其重要性不应该被忽略。
正文代码
1、头部标签(header标签)
这块区域之前以logo居多,而从目前的情况来看,很多资料都建议在这类使用标题1或2标签,即H1或H2标签。我们认为未来每个网页只会出现一个H1标签,而他的位置就是位于header标签内。该区域我们不建议使用strong标签,不要使用b标签。
2、导航标签(nav标签)
nav标签内基本上都是a标签,而HTML5中不应该靠添加title标签来进行优化,我们建议是用strong标签。
3、文章标签(article标签)
article标签区域,我们可以使用h2标签,而不建议使用h1标签。基本上有多少个article标签就可以使用多少个h2标签。
而article标签区域的section标签将会替代h2标签链接过去的URL的title属性,这块区域的文字有可能将成为目标URL的description内容, 即有可能会影响目标URL在SERP中的描述。
4、左或右侧标签(aside标签)
aside标签的文字信息与article标签区域的文字信息需要匹配,如果关联程度不大,可能会影响到该页面以及目标页面的排名。这是在HTML4中很多SEO忽视的一块区域,而这块区域的关键词对本页面可能影响不是很大。因为aside标签的内容基本上都属于公共内容,即会有N多的页面都有该内容。
5、底部标签(footer标签)
footer标签区域的内容对首页的排名将会增加,而对于内页来说搜索引擎将有可能会视而不见。不建议每个web的footer信息都是独立的,这或许意味着新的黑帽手段将会出现。
6、其他标签等
video标签中间区域的文字信息将会让搜索引擎读懂视频,这是一次飞跃。不过也为黑帽SEO节约了一笔不菲的时间。
audio标签作为类似img一样的单标签来处理感觉的确有点过分,这样对于音乐可能会有很多障碍,不过音乐里面基本上没有几个关键词,也就不再网页搜索引擎优化的研究范围了。注意下该标签上下文的关键词即可。
time标签可能会作为一个来判断网页文字源,也就是能够通过time标签来识别那篇文章是原创的。而time标签可能将是成为HTML5时代SEO们整理不休的一个标签。
noscript标签将会被大量使用,因为HTML5时代将会是一个富媒体时代。传统的文字、图片、链接、视频、音频可能已经满足不了用户的需求,大量的脚本能够编辑出丰富的信息,包括游戏、个性化设计等等。
PC浏览器前端优化策略
PC端优化的策略很多,如 YSlow(YSlow 是 Yahoo 发布的一款 Firefox 插件,现 Chrome 也可安装,可以对网站的页面性能进行分析,提出对该页面性能优化的建议)原则,或者 Chrome 自带的 Audits 等,总结起来主要包括网络加载类、页面渲染类、CSS 优化类、JavaScript 执行类、缓存类、图片类、架构协议类等几类,下面逐一介绍。
网络加载类
`1.减少 HTTP 资源请求次数`
在前端页面中,通常建议尽可能合并静态资源图片、JavaScript 或 CSS 代码,减少页面请求数和资源请求消耗,这样可以缩短页面首次访问的用户等待时间。通过构建工具合并雪碧图、CSS、JavaScript文件等都是为了减少 HTTP 资源请求次数。另外也要尽量避免重复的资源,防止增加多余请求。
`2.减小 HTTP 请求大小`
除了减少 HTTP 资源请求次数,也要尽量减小每个 HTTP 请求的大小。如减少没必要的图片、JavaScript、CSS 及 HTML 代码,对文件进行压缩优化,或者使用 gzip 压缩传输内容等都可以用来减小文件大小,缩短网络传输等待时延。前面我们使用构建工具来压缩静态图片资源以及移除代码中的注释并压缩,目的都是为了减小 HTTP 请求的大小。
`3.将 CSS 或 JavaScript 放到外部文件中,避免使用<style>或<script>标签直接引入`
在 HTML 文件中引用外部资源可以有效利用浏览器的静态资源缓存,但有时候在移动端页面 CSS 或 JavaScript 比较简单的情况下为了减少请求,也会将 CSS 或 JavaScript 直接写到 HTML 里面,具体要根据 CSS 或 JavaScript 文件的大小和业务的场景来分析。如果 CSS 或 JavaScript 文件内容较多,业务逻辑较复杂,建议放到外部文件引入。
<link rel="stylesheet" href="//cdn.domain.com/path/main.css" >
...
<script src="//cdn.domain.com/path/main.js"></script>
`4.避免页面中空的 href 和 src`
当<link>标签的 href 属性为空,或<script>、<img>、<iframe>标签的 src 属性为空时,浏览器在渲染的过程中仍会将 href 属性或 src 属性中的空内容进行加载,直至加载失败,这样就阻塞了页面中其他资源的下载进程,而且最终加载到的内容是无效的,因此要尽量避免。
<!--不推荐-->
<img src="" alt="photo" >
<a href="">点击链接</a>
`5.为 HTML 指定 Cache-Control 或 Expires`
为 HTML 内容设置 Cache-Control 或 Expires 可以将 HTML 内容缓存起来,避免频繁向服务器端发送请求。前面讲到,在页面 Cache-Control 或 Expires 头部有效时,浏览器将直接从缓存中读取内容,不向服务器端发送请求。
<meta http-equiv="Cache-Control" content="max-age=7200">
<meta http-equiv="Expires" content="Mon,20Jul201623:00:00GMT">
`6.合理设置 Etag 和 Last-Modified`
合理设置 Etag 和 Last-Modified 使用浏览器缓存,对于未修改的文件,静态资源服务器会向浏览器端返回304,让浏览器从缓存中读取文件,减少 Web 资源下载的带宽消耗并降低服务器负载。
<meta http-equiv="last-modified" content="Sun,05 Nov 2017 13:45:57 GMT">
`7.减少页面重定向`
页面每次重定向都会延长页面内容返回的等待延时,一次重定向大约需要200毫秒不等的时间开销(无缓存),为了保证用户尽快看到页面内容,要尽量避免页面重定向。
`8.使用静态资源分域存放来增加下载并行数`
浏览器在同一时刻向同一个域名请求文件的并行下载数是有限的,因此可以利用多个域名的主机来存放不同的静态资源,增大页面加载时资源的并行下载数,缩短页面资源加载的时间。通常根据多个域名来分别存储 JavaScript、CSS 和图片文件。
<link rel="stylesheet" href="//cdn1.domain.com/path/main.css" >
...
<script src="//cdn2.domain.com/path/main.js"></script>
`9.使用静态资源 CDN 来存储文件`
如果条件允许,可以利用 CDN 网络加快同一个地理区域内重复静态资源文件的响应下载速度,缩短资源请求时间。
`10.使用 CDN Combo 下载传输内容`
CDN Combo 是在 CDN 服务器端将多个文件请求打包成一个文件的形式来返回的技术,这样可以实现 HTTP 连接传输的一次性复用,减少浏览器的 HTTP 请求数,加快资源下载速度。例如同一个域名 CDN 服务器上的 a.js,b.js,c.js 就可以按如下方式在一个请求中下载。
<script src="//cdn.domain.com/path/a.js,b.js,c.js"></script>
`11.使用可缓存的 AJAX`
对于返回内容相同的请求,没必要每次都直接从服务端拉取,合理使用 AJAX 缓存能加快 AJAX 响应速度并减轻服务器压力。
$.ajax({
url : url,
type : 'get',
cache : true, //推荐使用缓存
data : {},
success (){//...},
error (){//...}
});
`12.使用 GET 来完成 AJAX 请求`
使用 XMLHttpRequest 时,浏览器中的 POST 方法会发起两次 TCP 数据包传输,首先发送文件头,然后发送 HTTP 正文数据。而使用 GET 时只发送头部,所以在拉取服务端数据时使用 GET 请求效率更高。
$.ajax({
url : url,
type : 'get', //推荐使用get完成请求
data : {},
success (){//...},
error(){//...}
});
`13.减少 Cookie 的大小并进行 Cookie 隔离`
HTTP 请求通常默认带上浏览器端的 Cookie 一起发送给服务器,所以在非必要的情况下,要尽量减少 Cookie 来减小 HTTP 请求的大小。对于静态资源,尽量使用不同的域名来存放,因为 Cookie 默认是不能跨域的,这样就做到了不同域名下静态资源请求的 Cookie 隔离。
`14.缩小 favicon.ico 并缓存`
有利于 favicon.ico 的重复加载,因为一般一个 Web 应用的 favicon.ico 是很少改变的。
`15.推荐使用异步 JavaScript 资源`
异步的 JavaScript 资源不会阻塞文档解析,所以允许在浏览器中优先渲染页面,延后加载脚本执行。例如 JavaScript 的引用可以如下设置,也可以使用模块化加载机制来实现。
<script src="main.js" defer></script>
<script src="main.js" async></script>
使用 async 时,加载和渲染后续文档元素的过程和 main.js 的加载与执行是并行的。使用 defer 时,加载后续文档元素的过程和 main.js 的加载是并行的,但是 main.js 的执行要在页面所有元素解析完成之后才开始执行。
`16.消除阻塞渲染的 CSS 及 JavaScript`
对于页面中加载时间过长的 CSS 或 JavaScript 文件,需要进行合理拆分或延后加载,保证关键路径的资源能快速加载完成。
`17.避免使用 CSS import 引用加载 CSS`
CSS 中的 @import 可以从另一个样式文件中引入样式,但应该避免这种用法,因为这样会增加 CSS 资源加载的关键路径长度,带有 @import 的 CSS 样式需要在 CSS 文件串行解析到 @import 时才会加载另外的 CSS 文件,大大延后 CSS 渲染完成的时间。
<!--不推荐-->
<style>
@import "path/main.css";
</style>
<!--推荐-->
<link rel="stylesheet" href="//cdn1.domain.com/path/main.css" >
页面渲染类
`1.把 CSS 资源引用放到 HTML 文件顶部`
一般推荐将所有 CSS 资源尽早指定在 HTML 文档 <head> 中,这样浏览器可以优先下载 CSS 并尽早完成页面渲染。
`2.JavaScript 资源引用放到 HTML 文件底部`
JavaScript 资源放到 HTML 文档底部可以防止 JavaScript 的加载和解析执行对页面渲染造成阻塞。由于 JavaScript 资源默认是解析阻塞的,除非被标记为异步或者通过其他的异步方式加载,否则会阻塞 HTML DOM 解析和 CSS 渲染的过程。
`3.尽量预先设定图片等大小`
在加载大量的图片元素时,尽量预先限定图片的尺寸大小,否则在图片加载过程中会更新图片的排版信息,产生大量的重排
`4.不要在 HTML 中直接缩放图片`
在 HTML 中直接缩放图片会导致页面内容的重排重绘,此时可能会使页面中的其他操作产生卡顿,因此要尽量减少在页面中直接进行图片缩放。
`5.减少 DOM 元素数量和深度`
HTML 中标签元素越多,标签的层级越深,浏览器解析 DOM 并绘制到浏览器中所花的时间就越长,所以应尽可能保持 DOM 元素简洁和层级较少。
<!--不推荐-->
<div>
<span>
<a href="javascript:void(0);">
<img src="./path/photo.jpg" alt="图片">
</a>
</span>
</div>
<!--推荐-->
<img src="./path/photo.jpg" alt="图片" >
`6.尽量避免在选择器末尾添加通配符`
CSS 解析匹配到 渲染树的过程是从右到左的逆向匹配,在选择器末尾添加通配符至少会增加一倍多计算量。
`7.减少使用关系型样式表的写法`
直接使用唯一的类名即可最大限度的提升渲染引擎绘制渲染树等效率
`8.尽量减少使用JS动画`
JS 直接操作 DOM 极容易引起页面的重排
`9.CSS 动画使用 translate、scale 代替 top、height`
尽量使用 CSS3 的 translate、scale 属性代替 top、left 和 height、width,避免大量的重排计算
`10.尽量避免使用<table>、<iframe>`
<table> 内容的渲染是将 table 的 DOM 渲染树全部生成完并一次性绘制到页面上的,所以在长表格渲染时很耗性能,应该尽量避免使用它,可以考虑使用列表元素 <ul> 代替。尽量使用异步的方式动态添加 iframe,因为 iframe 内资源的下载进程会阻塞父页面静态资源的下载与 CSS 及 HTML DOM 的解析。
`11.避免运行耗时的 JavaScript`
长时间运行的 JavaScript 会阻塞浏览器构建 DOM 树、DOM 渲染树、渲染页面。所以,任何与页面初次渲染无关的逻辑功能都应该延迟加载执行,这和 JavaScript 资源的异步加载思路是一致的。
`12.避免使用 CSS 表达式或 CSS 滤镜`
CSS 表达式或 CSS 滤镜的解析渲染速度是比较慢的,在有其他解决方案的情况下应该尽量避免使用。
//不推荐
.opacity{
filter : progid : DXImageTransform.Microsoft.Alpha( opacity = 50 );
}
移动端浏览器前端优化策略
相对于桌面端浏览器,移动端 Web 浏览器上有一些较为明显的特点:设备屏幕较小、新特性兼容性较好、支持一些较新的 HTML5 和 CSS3 特性、需要与 Native 应用交互等。但移动端浏览器可用的 CPU 计算资源和网络资源极为有限,因此要做好移动端 Web 上的优化往往需要做更多的事情。首先,在移动端 Web 的前端页面渲染中,桌面浏览器端上的优化规则同样适用,此外针对移动端也要做一些极致的优化来达到更好的效果。需要注意的是,并不是移动端的优化原则在桌面浏览器端就不适用,而是由于兼容性和差异性的原因,一些优化原则在移动端更具代表性。
网络加载类
`1.首屏数据请求提前,避免 JavaScript 文件加载后才请求数据`
为了进一步提升页面加载速度,可以考虑将页面的数据请求尽可能提前,避免在 JavaScript 加载完成后才去请求数据。通常数据请求是页面内容渲染中关键路径最长的部分,而且不能并行,所以如果能将数据请求提前,可以极大程度上缩短页面内容的渲染完成时间。
`2.首屏加载和按需加载,非首屏内容滚屏加载,保证首屏内容最小化`
由于移动端网络速度相对较慢,网络资源有限,因此为了尽快完成页面内容的加载,需要保证首屏加载资源最小化,非首屏内容使用滚动的方式异步加载。一般推荐移动端页面首屏数据展示延时最长不超过3秒。目前中国联通 3G 的网络速度为 338KB/s(2.71Mb/s),所以推荐首屏所有资源大小不超过 1014KB,即大约不超过 1MB。
`3.模块化资源并行下载`
在移动端资源加载中,尽量保证 JavaScript 资源并行加载,主要指的是模块化 JavaScript 资源的异步加载,例如AMD的异步模块,使用并行的加载方式能够缩短多个文件资源的加载时间。
`4.inline 首屏必备的 CSS 和 JavaScript`
通常为了在 HTML 加载完成时能使浏览器中有基本的样式,需要将页面渲染时必备的 CSS 和 JavaScript 通过 <script> 或 <style> 内联到页面中,避免页面 HTML 载入完成到页面内容展示这段过程中页面出现空白。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>样例</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<style>
/*必备的首屏CSS*/
html,body{
margin:0;
padding:0;
background-color:#ccc;
}
</style>
</head>
<body>
</body>
</html>
`5.meta dns prefetch 设置 DNS 预解析`
设置文件资源的 DNS 预解析,让浏览器提前解析获取静态资源的主机 IP,避免等到请求时才发起 DNS 解析请求。通常在移动端 HTML 中可以采用如下方式完成。
<!--cdn域名预解析-->
<meta http-equiv="x-dns-prefetch-control" content="on" >
<link rel="dns-prefetch" href="//cdn.domain.com" >
`6.资源预加载`
对于移动端首屏加载后可能会被使用的资源,需要在首屏完成加载后尽快进行加载,保证在用户需要浏览时已经加载完成,这时候如果再去异步请求就显得很慢。
`7.合理利用MTU策略`
通常情况下,我们认为 TCP 网络传输的最大传输单元(Maximum Transmission Unit,MTU)为 1500B,即一个RTT(Round-Trip Time,网络请求往返时间)内可以传输的数据量最大为 1500 字节。因此,在前后端分离的开发模式中,尽量保证页面的 HTML 内容在 1KB 以内,这样整个 HTML 的内容请求就可以在一个 RTT 内请求完成,最大限度地提高 HTML 载入速度。
缓存类
`1.合理利用浏览器缓存`
除了上面说到的使用 Cache-Control、Expires、Etag 和 Last-Modified 来设置 HTTP 缓存外,在移动端还可以使用 localStorage 等来保存 AJAX 返回的数据,或者使用 localStorage 保存 CSS 或 JavaScript 静态资源内容,实现移动端的离线应用,尽可能减少网络请求,保证静态资源内容的快速加载。
`2.静态资源离线方案`
对于移动端或 Hybrid 应用,可以设置离线文件或离线包机制让静态资源请求从本地读取,加快资源载入速度,并实现离线更新。关于这块内容,我们会在后面的章节中重点讲解。
`3.尝试使用 AMP HTML`
AMP HTML 可以作为优化前端页面性能的一个解决方案,使用 AMP Component 中的元素来代替原始的页面元素进行直接渲染。
<!--不推荐-->
<video width="400" height="300" src="http://www.domain.com/videos/myvideo.mp4"
poster="path/poster.jpg">
<div fallback>
<p>Your browser doesn’t support HTML5 video</p>
</div>
<source type="video/mp4" src="foo.mp4">
<source type="video/webm" src="foo.webm">
</video>
<!--推荐-->
<amp-video width="400" height="300" src="http://www.domain.com/videos/myvideo.mp4"
poster="path/poster.jpg">
<div fallback>
<p>Your browser doesn’t support HTML5 video</p>
</div>
<source type="video/mp4" src="foo.mp4">
<source type="video/webm" src="foo.webm">
</amp-video>
`4.尝试使用 PWA 模式`
PWA(Progressive Web Apps)是 Google 提出的用前沿的 Web 技术为网页提供 App 般使用体验的一系列方案。
图片类
`1.图片压缩处理`
在移动端,通常要保证页面中一切用到的图片都是经过压缩优化处理的,而不是以原图的形式直接使用的,因为那样很消耗流量,而且加载时间更长。
`2.使用较小的图片,合理使用 base64 内嵌图片`
在页面使用的背景图片不多且较小的情况下,可以将图片转化成 base64 编码嵌入到 HTML 页面或 CSS 文件中,这样可以减少页面的 HTTP 请求数。需要注意的是,要保证图片较小,一般图片大小超过 2KB 就不推荐使用 base64 嵌入显示了。
.class-name{
background-image : url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAALCAMAAABxsOwqAAAAYFBMVEWnxwusyQukxQudwQyZvgyhxAyfwgyxzAsUHQGOuA0aJAERGAFIXwSTugyEqgtqhghQZgUwQQIpOQKbuguVtQuKrAuCowp2kQlheghTbQZHWQU7SwVAVgQ6TgQlLwMeKwFOemyQAAAAVElEQVQI1y3JVRaAIAAF0UconXbvf5ei8HfPDIQQhBAAFE10iKig3SLRNN4SP/p+N08VC0YnfIlNWtqIkhg/TPYbCvhqdHAWRXPZSp3g3CWZvVLXC6OJA3ukv0AaAAAAAElFTkSuQmCC');
}
`3.使用更高压缩比格式的图片`
使用具有较高压缩比格式的图片,如 webp(需要设计降级兼容方案)等。在同等图片画质的情况下,高压缩比格式的图片体积更小,能够更快完成文件传输,节省网络流量。
<img src="//cdn.domain.com/path/photo.webp" alt="webp格式图片" >
`4.图片懒加载`
为了保证页面内容的最小化,加速页面的渲染,尽可能节省移动端网络流量,页面中的图片资源推荐使用懒加载实现,在页面滚动时动态载入图片。
<img data-src="//cdn.domain.com/path/photo.jpg" alt="懒加载图片" >
`5.使用 MediaQuery 或 srcset 根据不同屏幕加载不同大小图片`
在介绍响应式的章节中我们了解到,针对不同的移动端屏幕尺寸和分辨率,输出不同大小的图片或背景图能保证在用户体验不降低的前提下节省网络流量,加快部分机型的图片加载速度,这在移动端非常值得推荐。
`6.使用 iconfont 代替图片图标`
在页面中尽可能使用 iconfont 来代替图片图标,这样做的好处有以下几个:
使用 iconfont 体积较小,而且是矢量图,因此缩放时不会失真;
可以方便地修改图片大小尺寸和呈现颜色。
但是需要注意的是,iconfont 引用不同 webfont 格式时的兼容性写法,根据经验推荐尽量按照以下顺序书写,否则不容易兼容到所有的浏览器上。
@font-face{
font-family:iconfont;
src:url("./iconfont.eot");
src:url("./iconfont.eot?#iefix") format("eot"),
url("./iconfont.woff") format("woff"),
url("./iconfont.ttf") format("truetype");
}
`7.定义图片大小限制`
加载的单张图片一般建议不超过 30KB,避免大图片加载时间长而阻塞页面其他资源的下载,因此推荐在 10KB 以内。如果用户上传的图片过大,建议设置告警系统,帮助我们观察了解整个网站的图片流量情况,做出进一步的改善。
`8.强缓存策略`
对于一些「永远」不会变的图片可以使用强缓存的方式缓存在用户的浏览器上。
脚本类
`1.尽量使用 id`
选择器选择页面 DOM 元素时尽量使用 id 选择器,因为 id 选择器速度最快。
`2.合理缓存 DOM 对象`
对于需要重复使用的 DOM 对象,要优先设置缓存变量,避免每次使用时都要从整个DOM树中重新查找。
//不推荐
$('#mod.active').remove('active');
$('#mod.not-active').addClass('active');
//推荐
let $mod=$('#mod');
$mod.find('.active').remove('active');
$mod.find('.not-active').addClass('active');
`3.页面元素尽量使用事件代理,避免直接事件绑定`
使用事件代理可以避免对每个元素都进行绑定,并且可以避免出现内存泄露及需要动态添加元素的事件绑定问题,所以尽量不要直接使用事件绑定。
//不推荐
$('.btn').on('click',function(e){
console.log(this);
});
//推荐
$('body').on('click','.btn',function(e){
console.log(this);
});
`4.使用 touchstart 代替 click`
由于移动端屏幕的设计, touchstart 事件和 click 事件触发时间之间存在 300 毫秒的延时,所以在页面中没有实现 touchmove 滚动处理的情况下,可以使用 touchstart 事件来代替元素的 click 事件,加快页面点击的响应速度,提高用户体验。但同时我们也要注意页面重叠元素 touch 动作的点击穿透问题。
//不推荐
$('body').on('click','.btn',function(e){
console.log(this);
});
//推荐
$('body').on('touchstart','.btn',function(e){
console.log(this);
});
`5.避免 touchmove、scroll 连续事件处理`
需要对 touchmove、scroll 这类可能连续触发回调的事件设置事件节流,例如设置每隔 16ms(60 帧的帧间隔为 16.7ms,因此可以合理地设置为 16ms )才进行一次事件处理,避免频繁的事件调用导致移动端页面卡顿。
//不推荐
$('.scroller').on('touchmove','.btn',function(e){
console.log(this);
});
//推荐
$('.scroller').on('touchmove','.btn',function(e){
let self=this;
setTimeout(function(){
console.log(self);
},16);
});
`6.避免使用 eval、with,使用 join 代替连接符+,推荐使用 ECMAScript6 的字符串模板`
这些都是一些基础的安全脚本编写问题,尽可能使用较高效率的特性来完成这些操作,避免不规范或不安全的写法。
`7.尽量使用 ECMAScript6+的特性来编程`
ECMAScript6+ 一定程度上更加安全高效,而且部分特性执行速度更快,也是未来规范的需要,所以推荐使用 ECMAScript6+ 的新特性来完成后面的开发。
渲染类
`1.使用 Viewport 固定屏幕渲染,可以加速页面渲染内容`
一般认为,在移动端设置 Viewport 可以加速页面的渲染,同时可以避免缩放导致页面重排重绘。在移动端固定 Viewport 设置的方法如下。
<!--设置viewport不缩放-->
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
`2.避免各种形式重排重绘`
页面的重排重绘很耗性能,所以一定要尽可能减少页面的重排重绘,例如页面图片大小变化、元素位置变化等这些情况都会导致重排重绘。
`3.使用 CSS3 动画,开启GPU加速`
使用 CSS3 动画时可以设置 transform:translateZ(0) 来开启移动设备浏览器的GPU图形处理加速,让动画过程更加流畅,但需要注意的是,在 Native WebView 下 GPU 加速有几率产生 App Crash。
-webkit-transform:translateZ(0);
-ms-transform:translateZ(0);
-o-transform:translateZ(0);
transform:translateZ(0);
`4.合理使用 Canvas 和 requestAnimationFrame`
选择 Canvas 或 requestAnimationFrame 等更高效的动画实现方式,尽量避免使用 setTimeout、setInterval 等方式来直接处理连续动画。
`5.SVG 代替图片`
部分情况下可以考虑使用 SVG 代替图片实现动画,因为使用 SVG 格式内容更小,而且 SVG DOM 结构方便调整。
`6.不滥用 float`
在 DOM 渲染树生成后的布局渲染阶段,使用 float 的元素布局计算比较耗性能,所以尽量减少 float 的使用,推荐使用固定布局或 flex-box 弹性布局的方式来实现页面元素布局。
`7.不滥用 web 字体或过多 font-size 声明`
过多的 font-size 声明会增加字体的大小计算,而且也没有必要的。
`8.做好脚本容错`
脚本容错可以避免「非正常环境」的执行错误影响页面的加载和不相关功能的使用
架构协议类
`1.尝试使用 SPDY 和 HTTP2`
在条件允许的情况下可以考虑使用 SPDY 协议来进行文件资源传输,利用连接复用加快传输过程,缩短资源加载时间。HTTP2 在未来也是可以考虑尝试的。
`2.使用后端数据渲染`
使用后端数据渲染的方式可以加快页面内容的渲染展示,避免空白页面的出现,同时可以解决移动端页面SEO的问题。如果条件允许,后端数据渲染是一个很不错的实践思路。后面的章节会详细介绍后端数据渲染的相关内容。
`3.使用 NativeView 代替 DOM 的性能劣势`
可以尝试使用 NativeView 的 MNV* 开发模式来避免 HTML DOM 性能慢的问题,目前使用 MNV* 的开发模式已经可以将页面内容渲染体验做到接近客户端 Native 应用的体验了。但需要避免 js Framework 和 native Framework 的频繁交互。
结束啦~~
什么是跨域?
同源策略是由Netscape提出的著名安全策略,是浏览器最核心、基本的安全功能,它限制了一个源(origin)中加载文本或者脚本与来自其他源(origin)中资源的交互方式,所谓的同源就是指协议、域名、端口相同。
当浏览器执行一个脚本时会检查是否同源,只有同源的脚本才会执行,如果不同源即为跨域
跨域的几种方式:
1、jsonp
最常见的一种跨域方式,其背后原理就是利用了script标签不受同源策略的限制,在页面中动态插入了script,script标签的src属性就是后端api接口的地址,并且以get的方式将前端回调处理函数名称告诉后端,后端在响应请求时会将回调返还,并且将数据以参数的形式传递回去。
前端:
//http://127.0.0.1:8888/jsonp.html
var script = document.createElement('script');
script.src = 'http://127.0.0.1:2333/jsonpHandler?callback=_callback'
document.body.appendChild(script); //插入script标签
//回调处理函数 _callback
var _callback = function(obj){
for(key in obj){
console.log('key: ' + key +' value: ' + obj[key]);
}
}
后端:
//http://127.0.0.1:2333/jsonpHandler
app.get('/jsonpHandler', (req,res) => {
let callback = req.query.callback;
let obj = {
type : 'jsonp',
name : 'weapon-x'
};
res.writeHead(200, {"Content-Type": "text/javascript"});
res.end(callback + '(' + JSON.stringify(obj) + ')');
})
2、CORS
Cross-Origin Resource Sharing(跨域资源共享)是一种允许当前域(origin)的资源(比如html/js/web service)被其他域(origin)的脚本请求访问的机制。
当使用XMLHttpRequest发送请求时,浏览器如果发现违反了同源策略就会自动加上一个请求头:origin,后端在接受到请求后确定响应后会在Response Headers中加入一个属性:Access-Control-Allow-Origin,值就是发起请求的源地址(http://127.0.0.1:8888),浏览器得到响应会进行判断Access-Control-Allow-Origin的值是否和当前的地址相同,只有匹配成功后才进行响应处理。
现代浏览器中和移动端都支持CORS(除了opera mini),IE下需要8+
前端:
//http://127.0.0.1:8888/cors.html
var xhr = new XMLHttpRequest();
xhr.onload = function(data){
var _data = JSON.parse(data.target.responseText)
for(key in _data){
console.log('key: ' + key +' value: ' + _data[key]);
}
};
xhr.open('POST','http://127.0.0.1:2333/cors',true);
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send();
后端:
//http://127.0.0.1:2333/cors
app.post('/cors',(req,res) => {
if(req.headers.origin){
res.writeHead(200,{
"Content-Type": "text/html; charset=UTF-8",
"Access-Control-Allow-Origin":'http://127.0.0.1:8888'
});
let people = {
type : 'cors',
name : 'weapon-x'
}
res.end(JSON.stringify(people));
}
})
3、服务器跨域
在前后端分离的项目中可以借助服务器实现跨域,具体做法是:前端向本地服务器发送请求,本地服务器代替前端再向api服务器接口发送请求进行服务器间通信,本地服务器其实就是个中转站的角色,再将响应的数据返回给前端,下面用node.js做一个示例
前端:
//http://127.0.0.1:8888/server
var xhr = new XMLHttpRequest();
xhr.onload = function(data){
var _data = JSON.parse(data.target.responseText)
for(key in _data){
console.log('key: ' + key +' value: ' + _data[key]);
}
};
xhr.open('POST','http://127.0.0.1:8888/feXhr',true); //向本地服务器发送请求
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
xhr.send("url=http://127.0.0.1:2333/beXhr"); //以参数形式告知需要请求的后端接口
后端:
//http://127.0.0.1:8888/feXhr
app.post('/feXhr',(req,res) => {
let url = req.body.url;
superagent.get(url) //使用superagent想api接口发送请求
.end(function (err,docs) {
if(err){
console.log(err);
return
}
res.end(docs.res.text); //返回到前端
})
})
//http://127.0.0.1:2333/beXhr
app.get('/beXhr',(req,res) => {
let obj = {
type : 'superagent',
name : 'weapon-x'
};
res.writeHead(200, {"Content-Type": "text/javascript"});
res.end(JSON.stringify(obj)); //响应
})
4、postmessage跨域
在HTML5中新增了postMessage方法,postMessage可以实现跨文档消息传输(Cross Document Messaging),Internet Explorer 8, Firefox 3, Opera 9, Chrome 3和 Safari 4都支持postMessage。
该方法可以通过绑定window的message事件来监听发送跨文档消息传输内容。
使用postMessage实现跨域的话原理就类似于jsonp,动态插入iframe标签,再从iframe里面拿回数据,私认为用作跨页面通信更加适合。
--------------------------------------------- 华丽的分界线 ------------------------------------------------
HTTP状态码及其含义
**1XX:信息状态码**
100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
**2XX:成功状态码**
200 OK 正常返回信息
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求,但尚未处理
**3XX:重定向**
301 Moved Permanently 请求的网页已永久移动到新位置。
302 Found 临时性重定向。
303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。
304 Not Modified 自从上次请求后,请求的网页未修改过。
**4XX:客户端错误**
400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
401 Unauthorized 请求未授权。
403 Forbidden 禁止访问。
404 Not Found 找不到如何与 URI 相匹配的资源。
**5XX: 服务器错误**
500 Internal Server Error 最常见的服务器端错误。
503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。
--------------------------------------------- 华丽的分界线 ------------------------------------------------
从浏览器地址栏输入url到显示页面的步骤
1.在浏览器地址栏输入URL
2.浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤
1.如果资源未缓存,发起新请求
2.如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证。
3.检验新鲜通常有两个HTTP头进行控制Expires和Cache-Control:
HTTP1.0提供Expires,值为一个绝对时间表示缓存新鲜日期
HTTP1.1增加了Cache-Control: max-age=,值为以秒为单位的最大新鲜时间
3.浏览器解析URL获取协议,主机,端口,path
4.浏览器组装一个HTTP(GET)请求报文
5.浏览器获取主机ip地址,过程如下:
1.浏览器缓存
2.本机缓存
3.hosts文件
4.路由器缓存
5.ISP DNS缓存
6.DNS递归查询(可能存在负载均衡导致每次IP不一样)
6.打开一个socket与目标IP地址,端口建立TCP链接,三次握手如下:
客户端发送一个TCP的SYN=1,Seq=X的包到服务器端口
服务器发回SYN=1, ACK=X+1, Seq=Y的响应包
客户端发送ACK=Y+1, Seq=Z
7.TCP链接建立后发送HTTP请求
8.服务器接受请求并解析,将请求转发到服务程序,如虚拟主机使用HTTP Host头部判断请求的服务程序
9.服务器检查HTTP请求头是否包含缓存验证信息如果验证缓存新鲜,返回304等对应状态码
10.处理程序读取完整请求并准备HTTP响应,可能需要查询数据库等操作
11.服务器将响应报文通过TCP连接发送回浏览器
12.浏览器接收HTTP响应,然后根据情况选择关闭TCP连接或者保留重用,关闭TCP连接的四次握手如下:
主动方发送Fin=1, Ack=Z, Seq= X报文
被动方发送ACK=X+1, Seq=Z报文
被动方发送Fin=1, ACK=X, Seq=Y报文
主动方发送ACK=Y, Seq=X报文
13.浏览器检查响应状态码:是否为1XX,3XX, 4XX, 5XX,这些情况处理与2XX不同
14.如果资源可缓存,进行缓存
15.对响应进行解码(例如gzip压缩)
16.根据资源类型决定如何处理(假设资源为HTML文档)
17.解析HTML文档,构件DOM树,下载资源,构造CSSOM树,执行js脚本,这些操作没有严格的先后顺序,以下分别解释
18.构建DOM树:
Tokenizing:根据HTML规范将字符流解析为标记
Lexing:词法分析将标记转换为对象并定义属性和规则
DOM construction:根据HTML标记关系将对象组成DOM树
19.解析过程中遇到图片、样式表、js文件,启动下载
20.构建CSSOM树:
Tokenizing:字符流转换为标记流
Node:根据标记创建节点
CSSOM:节点创建CSSOM树
21.根据DOM树和CSSOM树构建渲染树:
1.从DOM树的根节点遍历所有可见节点,不可见节点包括:1)script,meta这样本身不可见的标签。2)被css隐藏的节点,如display: none
2.对每一个可见节点,找到恰当的CSSOM规则并应用
3.发布可视节点的内容和计算样式
22.js解析如下:
1.浏览器创建Document对象并解析HTML,将解析到的元素和文本节点添加到文档中,此时document.readystate为loading
2.HTML解析器遇到没有async和defer的script时,将他们添加到文档中,然后执行行内或外部脚本。这些脚本会同步执行,并且在脚本下载和执行时解析器会暂停。这样就可以用document.write()把文本插入到输入流中。同步脚本经常简单定义函数和注册事件处理程序,他们可以遍历和操作script和他们之前的文档内容
3.当解析器遇到设置了async属性的script时,开始下载脚本并继续解析文档。脚本会在它下载完成后尽快执行,但是解析器不会停下来等它下载。异步脚本禁止使用document.write(),它们可以访问自己script和之前的文档元素
4.当文档完成解析,document.readState变成interactive
5.所有defer脚本会按照在文档出现的顺序执行,延迟脚本能访问完整文档树,禁止使用document.write()
6.浏览器在Document对象上触发DOMContentLoaded事件
7.此时文档完全解析完成,浏览器可能还在等待如图片等内容加载,等这些内容完成载入并且所有异步脚本完成载入和执行,document.readState变为complete,window触发load事件
23.显示页面(HTML解析过程中会逐步显示页面)
(有点详细,面试时候肯定没时间讲这么多,不过对于理解还是很有用哒~~)