HTTP的几种请求方法用途
- 1)GET方法 发送一个请求来取得服务器上的某一资源
- 2)POST方法 向URL指定的资源提交数据或附加新的数据
- 3)PUT方法 跟POST方法很像,也是想服务器提交数据。但是,它们之间有不同。PUT指定了资源在服务器上的位置,而POST没有
- 4)HEAD方法 只请求页面的首部
- 5)DELETE方法 删除服务器上的某资源
- 6)OPTIONS方法 它用于获取当前URL所支持的方法。如果请求成功,会有一个Allow的头包含类似“GET,POST”这样的信息
- 7)TRACE方法 TRACE方法被用于激发一个远程的,应用层的请求消息回路
- 8)CONNECT方法 把请求连接转换到透明的TCP/IP通道
POST和GET的区别
-
在浏览器进行回退操作时,get请求是无害的,而post请求则会重新请求一次
-
get请求参数是连接在url后面的,而post请求参数是存放在requestbody内的
-
get请求因为浏览器对url长度有限制(不同浏览器长度限制不一样)对传参数量有限制,而post请求因为参数存放在requestbody内所以参数数量没有限制(事实上get请求也能在requestbody内携带参数,只不过不符合规定,有的浏览器能够获取到数据,而有的不能),大小get不超过2KB,post无限制
-
因为get请求参数暴露在url上,所以安全方面post比get更加安全
-
get请求浏览器会主动cache,post并不会,除非主动设置
-
get请求参数会保存在浏览器历史记录内,post请求并不会
-
get请求只能进行url编码,而post请求可以支持多种编码方式
-
get请求产生1个tcp数据包,post请求产生2个tcp数据包
-
浏览器在发送get请求时会将header和data一起发送给服务器,服务器返回200状态码,而在发送post请求时,会先将header发送给服务器,服务器返回100,之后再将data发送给服务器,服务器返回200 OK
从浏览器地址栏输入URL到显示页面的步骤
1、域名解析 当我们在浏览器中输入一个URL,例如”www.google.com”时,这个地址并不是谷歌网站真正意义上的地址。互联网上每一台计算机的唯一标识是它的IP地址,因此我们输入的网址首先需要先解析为IP地址,这一过程叫做DNS解析。
DNS解析是一个递归查询的过程。例如,我们需要解析”www.google.com”时,会经历以下步骤:
在本地域名服务器中查询IP地址,未找到域名; 本地域名服务器回向根域名服务器发送请求,未找到域名; 本地域名服务器向.com顶级域名服务器发送请求,未找到域名; 本地域名服务器向.google.com域名服务器发送请求,找到该域名,将对应的IP返回给本地域名服务器。
2、TCP连接
HTTP协议是使用TCP协议作为其传输层协议的,在拿到服务器的IP地址后,浏览器客户端会与服务器建立TCP连接。该过程包括三次握手:
第一次握手:建立连接时,客户端向服务端发送请求报文 第二次握手:服务器收到请求报文后,如同意连接,则向客户端发送确认报文 第三次握手,客户端收到服务器的确认后,再次向服务器给出确认报文,完成连接。 三次握手主要是为了防止已经失效的请求报文字段发送给服务器,浪费资源。
3、浏览器发送HTTP请求
浏览器构建http请求报文,并通过TCP协议传送到服务器的指定端口。http请求报文一共包括三个部分:
请求行:指定http请求的方法、url、http协议版本等 请求头:描述浏览器的相关信息,语言、编码等。如下
4、服务器处理HTTP请求
服务器处理http请求,并返回响应报文。响应报文包括三个部分:
状态码:http服务常用的状态码及其含义如下 状态码 含义 常见示例
-
1** 服务器已经接受到请求,客户端可继续发送请求
-
2** 请求成功 200:请求已成功,请求所希望的响应头或数据体将随此响应返回。
-
3** 重定向 303:对应当前请求的响应可以在另一个 URI 上被找到,而且客户端应当采用 GET 的方式访问那个资源。304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
-
4** 客户端错误 400(错误请求) 服务器不理解请求的语法。403(禁止) 服务器拒绝请求。 404:请求的网页不存在 405(方法禁用) 禁用请求中指定的方法。
-
5** 服务器错误 503: 服务器超时
-
响应头:包含了响应的相关信息,如日期等
-
响应正文:服务器返回给浏览器的文本信息,通常的html、js、css、图片等就包含在这一部分里面。
5、浏览器页面渲染
浏览器接受到http服务器发送过来的响应报文,并开始解析html文档,渲染页面。具体的渲染过程包括:构建DOM树、构建渲染树、定位页面元素、绘制页面元素等。具体可参看:浏览器时如何渲染页面的
6、断开TCP连接
客户端与服务器四次挥手,断开tcp连接。
第一次挥手:客户端想分手,发送消息给服务器 第二次挥手:服务器通知客户端已经接受到分手请求,但还没做好分手准备 第三次回收:服务器已经做好分手准备,通知客户端 第四次挥手:客户端发送消息给服务器,确定分手,服务器关闭连接
HTML5有哪些新特性、移除了哪些元素?
-
绘画 canvas;
-
用于媒介回放的 video和 audio元素;
-
语意化更好的内容元素,比如article、footer、header、nav、section;
-
本地离线存储 localStorage
localStorage.getItem()
localStorage.setItem()
localStorage.removeItem()
- sessionStorage的数据在浏览器关闭后自动删除;操作参考localStorage
- 事件监听
if(window.addEventListener){
window.addEventListener("storage",handle_storage,false);//
}else if(window.attachEvent){ //兼容IE
window.attachEvent("onstorage",handle_storage);
}
function handle_storage(e){}
移除:
<basefont> 默认字体,不设置字体,以此渲染
<font> 字体标签
<center> 水平居中
<u> 下划线
<big> 大字体
<strike> 中横线
<tt> 文本等宽
<frameset>
<noframes>
<frame>
请描述一下cookies,sessionStorage和localStorage的区别?
cookie 是网站为了标识用户信息而存储在本地(client side)上的数据,一般会加密
cookie数据始终在同源请求中传递,即在浏览器和服务器之间来回传递
seesionstorage 和 localstorage 不会把数据发到服务器,仅在本地保存
存储大小,cookie的大小不能超过4k sessionstorage 和 localstorage 的大小一般在5M以上,比cookie大的多
有效时间不同
localstorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据
sessionstorage 数据在当前浏览器窗口关闭或者会话结束后自动删除
cookie 设置的cookie过期之前一直有效,即使窗口或者浏览器关闭
存储位置 cookie未设置expires时候,存在内存中,设置时间后存在硬盘中;sessionstorage存放在内存里;localstorage存放在硬盘。
节流函数和防抖函数
函数防抖(debounce)
函数防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。简单的说,当一个动作连续触发,则只执行最后一次。
函数防抖的应用场景
连续的事件,只需触发一次回调的场景有:
-
搜索框搜索输入。只需用户最后一次输入完,再发送请求
-
手机号、邮箱验证输入检测
-
窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
let debounce = function(fn, delay) {
let _timer = null;//利用闭包,一直存在
return function () {
let content = this;
let args = [].slice.call(arguments);//把event对象传过去
if(_timer){clearTimeout(_timer);}
_timer = setTimeout(function () {
fn.apply(content,args);
}, delay);
};
};
函数防抖在执行目标方法时,会等待一段时间。当又执行相同方法时,若前一个定时任务未执行完,则 clear 掉定时任务,重新定时。
函数节流(throttle)
限制一个函数在一定时间内只能执行一次。
函数节流应用场景
间隔一段时间执行一次回调的场景有:
-
滚动加载,加载更多或滚到底部监听
-
谷歌搜索框,搜索联想功能
-
高频点击提交,表单重复提交
// 定时器方案
function throttle(fn,wait){
var timer = null;
return function(){
var context = this;
var args = arguments;
if(!timer){
timer = setTimeout(function(){
fn.apply(context,args);
timer = null;
},wait)
}
}
}
function handle(){
console.log(Math.random());
}
window.addEventListener("mousemove",throttle(handle,1000));
// 时间戳方案
function throttle(fn,wait){
var pre = Date.now();
return function(){
var context = this;
var args = arguments;
var now = Date.now();
if( now - pre >= wait){
fn.apply(context,args);
pre = Date.now();
}
}
}
function handle(){
console.log(Math.random());
}
window.addEventListener("mousemove",throttle(handle,1000));
相同点:
-
都可以通过使用 setTimeout 实现。
-
目的都是,降低回调执行频率。节省计算资源。
不同点:
-
函数防抖,在一段连续操作结束后,处理回调,利用 clearTimeout 和 setTimeout 实现。
-
函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。
-
函数防抖关注一定时间连续触发,只在最后执行一次,而函数节流侧重于一段时间内只执行一次。
简述vue和react的区别
React 和Vue是现在主流的两个框架(相对来说angular用的已经少了)
两者的区别体现在以下方面
相同点:
1、react和vue都支持服务端渲染
2、都有虚拟DOM,组件化开发,通过props传参进行父子组件数据的传递
3、都是数据驱动视图
4、都有支持native的方案(react的react native,vue的weex)
5、都有状态管理(react有redux,vue有vuex)
不同点:
1、react严格上只能算是MVC的view层,vue则是MVVM模式
2、虚拟DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树
而对于react而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制
3、组件写法不一样,react推荐的做法是JSX+inline style,也就是把HTML和CSS全都写进javaScript了
4、数据绑定:vue实现了数据的双向绑定,react数据流动是单向的
5、state对象在react应用中是不可变的,需要使用setState方法更新状态
在vue中,state对象不是必须的,数据有data属性在vue对象中管理
谈谈正则
1、元字符
2、重复限定符
node.js的特点以及优缺点
特点
Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台。
Node.js是一个事件驱动I/O服务端JavaScript环境,基于Google的V8引擎,V8引擎执行Javascript的速度非常快,性能非常好
优点
动态语言:开发效率非常高,并有能力构建复杂系统,如ql.io。
性能和I/O负载:Nodejs非常好的解决了IO密集的问题,通过异步IO来实现。libuv是一个多平台支持库,主要关注异步I/O。
连接的内存开销:每个Node.js进程可以支持超过12万活跃的连接,每个连接消耗大约2K的内存。
操作性:实现了Nodejs对于内存堆栈的监控系统。
缺点
nodejs更新很快,可能会出现版本兼容
nodejs还不算成熟,还没有大制作
nodejs不像其他的服务器,对于不同的链接,不支持进程和线程操作
node如何实现前后端分离以及好处
试想一下,如果前端掌握了Controller,我们可以做url design,我们可以根据场景决定在服务端同步渲染,还是根据view层数据输出json数据,我们还可以根据表现层需求很容易的做bigpipe,comet,socket等等,完全是需求决定使用方式。
现阶段我们主要以后端MVC的模式进行开发,这种模式严重阻碍了前端开发效率,也让后端不能专注于业务开发。 解决方案是让前端能控制Controller层,但是如果在现有技术体系下很难做到,因为不可能让所有前端都学java,安装后端的开发环境,写VM。 NodeJS就能很好的解决这个问题,我们无需学习一门新的语言,就能做到以前开发帮我们做的事情,一切都显得那么自然。
分层就涉及每层之间的通讯,肯定会有一定的性能损耗。但是合理的分层能让职责清晰、也方便协作,会大大提高开发效率。分层带来的损失,一定能在其他方面的收益弥补回来。 另外,一旦决定分层,我们可以通过优化通讯方式、通讯协议,尽可能把损耗降到最低。
PC端和手机端的区别
第一: PC考虑的是浏览器的兼容性,而移动端开发考虑的更多的是手机兼容性,因为目前不管是android手机还是ios手机,一般浏览器使用的都是webkit内核,所以说做移动端开发,更多考虑的应该是手机分辨率的适配,和不同操作系统的略微差异化。
第二: 在部分事件的处理上,移动端多出来的事件是触屏事件,而缺少的是hover事件。 另外包括移动端弹出的手机键盘的处理,这样的问题在PC端都是遇不到的。
第三: 在布局上,移动端开发一般是要做到布局自适应的,我使用的一直是rem布局,感觉很好。
@function px2rem($px, $base: 75) {
@return ($px / $base) * 1rem;
}
/*
稿子上量得某按钮宽60px,高20px
*/
.btn{
width:px2rem(60);
height:px2rem(20);
}
第四: 在动画处理上,PC端由于要考虑IE的兼容性,所以通常使用JS做动画的通用性会更好一些,但是CSS3做了很大的牺牲, 而在手机端,如果要做一些动画、特效等,第一选择肯定是CSS3, 既简单、效率又高。
CSS有哪些属性是可以继承的?
一、无继承性的属性
1、display:规定元素应该生成的框的类型
2、文本属性:
vertical-align:垂直文本对齐
text-decoration:规定添加到文本的装饰
text-shadow:文本阴影效果
white-space:空白符的处理
unicode-bidi:设置文本的方向
3、盒子模型的属性:width、height、margin 、margin-top、margin-right、margin-bottom、margin-left、border、border-style、border-top-style、border-right-style、border-bottom-style、border-left-style、border-width、border-top-width、border-right-right、border-bottom-width、border-left-width、border-color、border-top-color、border-right-color、border-bottom-color、border-left-color、border-top、border-right、border-bottom、border-left、padding、padding-top、padding-right、padding-bottom、padding-left
4、背景属性:background、background-color、background-image、background-repeat、background-position、background-attachment
5、定位属性:float、clear、position、top、right、bottom、left、min-width、min-height、max-width、max-height、overflow、clip、z-index
6、生成内容属性:content、counter-reset、counter-increment
7、轮廓样式属性:outline-style、outline-width、outline-color、outline
8、页面样式属性:size、page-break-before、page-break-after
9、声音样式属性:pause-before、pause-after、pause、cue-before、cue-after、cue、play-during 二、有继承性的属性
1、字体系列属性
font:组合字体
font-family:规定元素的字体系列
font-weight:设置字体的粗细
font-size:设置字体的尺寸
font-style:定义字体的风格
font-variant:设置小型大写字母的字体显示文本,这意味着所有的小写字母均会被转换为大写,但是所有使用小型大写字体的字母与其余文本相比,其字体尺寸更小。
font-stretch:对当前的 font-family 进行伸缩变形。所有主流浏览器都不支持。
font-size-adjust:为某个元素规定一个 aspect 值,这样就可以保持首选字体的 x-height。
2、文本系列属性
text-indent:文本缩进
text-align:文本水平对齐
line-height:行高
word-spacing:增加或减少单词间的空白(即字间隔)
letter-spacing:增加或减少字符间的空白(字符间距)
text-transform:控制文本大小写
direction:规定文本的书写方向
color:文本颜色
3、元素可见性:visibility
4、表格布局属性:caption-side、border-collapse、border-spacing、empty-cells、table-layout
5、列表布局属性:list-style-type、list-style-image、list-style-position、list-style
6、生成内容属性:quotes
7、光标属性:cursor
8、页面样式属性:page、page-break-inside、windows、orphans
9、声音样式属性:speak、speak-punctuation、speak-numeral、speak-header、speech-rate、volume、voice-family、pitch、pitch-range、stress、richness、、azimuth、elevation
三、所有元素可以继承的属性
1、元素可见性:visibility
2、光标属性:cursor
四、内联元素可以继承的属性
1、字体系列属性
2、除text-indent、text-align之外的文本系列属性
五、块级元素可以继承的属性
1、text-indent、text-align
css4新增特性
1.否定伪类:not
否定伪类选择器其实在CSS3选择器中就出现了,只不过CSS4选择器对否定伪类选择器升级了。在CSS3中,你可以通过否定伪类选择器不去选中你不需要用到的CSS样式的元素。比如说,你想除了.intro的段落之外文本都不加粗,你就可以这样使用伪类选择器。
p:not(.intro) { font-weight: normal; }
在CSS4选择器中,可以传入一个逗号(,)分隔的列表选择器:
p:not(.intro, blockquote) { font-weight: normal; }
2.匹配任何伪类:matches
这个伪类意味着,可以将规则应用到一个组合选择器中,如:
p:matches(.alert, .error, .warn) { color: red; }
带有只要元素带
带有.alert、.error和.warn中任何一个类名,文本颜色都将会是red。
你可以在http://css4-selectors.com网站上测试你的浏览器是否支持这些CSS4选择器。这也是一个资源网站,你可以在这个站上找到将要添加的选择器。
3.关系伪类:has
这个选择器通过一个参数从一个列表选择器中匹配到相对应的元素。有一个最易说明的示例,在这个例子中任何一个包含的链接都会加上一个黑色的边框:
a:has( > img ) { border: 1px solid #000; }
在下面这个示例中,使用:has和:not结合在一起,选择不包含段落
的元素:
li:not(:has(p)){ padding-bottom: 1em; }
4.表单限制伪类 :required:optional
匹配表单项中必选项与可选项。
input:required { color:#f30; }
5.可读可写伪类 :read-write、:read-only
大部分元素都是可读不可写的,所以都是 :read-only;像 text input 这些值可以改变的,和 HTML5 中设置了 contenteditable 的元素其本身是可改变的,这些被认为是具有写属性的,所以是 :read-write
:read-write { font-family: Georgia; }
- :any-link
目前,我们可以使用:link和:visited表明链接的访问状态。这个更进一步,它会检查href的是否在用户的浏览历史中存在,以确定是否一个给定的链接是否已被访问。
:link, :visited {
color: blue;
}
css4 ,可以直接这样应用,上述代码等价于:
:any-link {
color: blue;
}
7.:scoped
css4选择器,CSS被赋予一个全局范围。换句话说,如果你添加下面的CSS:
div {
color: #444;
}
所有的div将应用的 color:#444 的样式规则(这里假设没有被复写的情况下)。css4选择器 允许将样式和风格限定于一个元素标签内。
在这个例子中,我们已将应用范围到限定在aside元素中。在这种标记风格将只适用于父元素下的子元素。
8.css网格布局
网格布局为我们创建了类似于表格布局的结构,然而,我们可以使用CSS而非HTML中所描述的选择器来创建布局,通过媒体查询来重定义布局以适应不同的上下文内容。这样我们就可以正确区分视觉和源码的元素顺序。作为一个设计师,你可以自由地改变页面元素的位置来适应不同断点下的布局,而不必为你响应式设计去调整结构。与HTML中基于表格的布局不同,网格布局允许你堆叠元素。因此,在需要的情况下,一个元素可以重叠另一元素。
原型链 以及属性
简单的回顾一下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。——摘自《javascript高级程序设计》
vue首屏性能优化,解决页面加载时间过长(白屏)方法
优化策略:
1、路由懒加载
- vue异步组件
- es提案的import()
- webpack的require,ensure()
vue异步组件技术 ==== 异步加载
vue-router配置路由 , 使用vue的异步组件技术 , 可以实现按需加载 . 但是,这种情况下一个组件生成一个js文件
/* vue异步组件技术 */
{
path: '/home',
name: 'home',
component: resolve => require(['@/components/home'],resolve)
},{
path: '/index',
name: 'Index',
component: resolve => require(['@/components/index'],resolve)
},{
path: '/about',
name: 'about',
component: resolve => require(['@/components/about'],resolve)
}
/* 注意resolve和require两边的空格 */
组件懒加载方案二 路由懒加载(使用import)
// 下面3行代码,没有指定webpackChunkName,每个组件打包成一个js文件。
/* const Home = () => import('@/components/home')
const Index = () => import('@/components/index')
const About = () => import('@/components/about') */
// 下面3行代码,指定了相同的webpackChunkName,会合并打包成一个js文件。 把组件按组分块
const Home = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/home')
const Index = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/index')
const About = () => import(/* webpackChunkName: 'ImportFuncDemo' */ '@/components/about')
{
path: '/about',
component: About
}, {
path: '/index',
component: Index
}, {
path: '/home',
component: Home
}
webpack提供的require.ensure()
vue-router配置路由,使用webpack的require.ensure技术,也可以实现按需加载。 这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。
/* 组件懒加载方案三: webpack提供的require.ensure() */
{
path: '/home',
name: 'home',
component: r => require.ensure([], () => r(require('@/components/home')), 'demo')
}, {
path: '/index',
name: 'Index',
component: r => require.ensure([], () => r(require('@/components/index')), 'demo')
}, {
path: '/about',
name: 'about',
component: r => require.ensure([], () => r(require('@/components/about')), 'demo-01')
}
如果是在 vuecli 3中,我们还需要多做一步工作 因为 vuecli 3默认开启 prefetch(预先加载模块),提前获取用户未来可能会访问的内容 在首屏会把这十几个路由文件,都一口气下载了 所以我们要关闭这个功能,在 vue.config.js中设置:
2、ui框架按需加载 这里以饿了么ui为例: 原本的引进方式引进了整个包:
import ElementUI from 'element-ui'
Vue.use(ElementUI)
但实际上我用到的组件只有按钮,分页,表格,输入与警告 所以我们要按需引用:
import { Button, Input, Pagination, Table, TableColumn, MessageBox } from 'element-ui';
Vue.use(Button)
Vue.use(Input)
Vue.use(Pagination)
Vue.prototype.$alert = MessageBox.alert
3、gzip压缩
安装 compression-webpack-plugin
cnpm i compression-webpack-plugin -D
const CompressionPlugin = require('compression-webpack-plugin')
在 vue.congig.js中引入并修改 webpack配置:
configureWebpack: (config) => {
if (process.env.NODE_ENV === 'production') {
// 为生产环境修改配置...
config.mode = 'production'
return {
plugins: [new CompressionPlugin({
test: /\.js$|\.html$|\.css/, //匹配文件名
threshold: 10240, //对超过10k的数据进行压缩
deleteOriginalAssets: false //是否删除原文件
})]
}
}
在服务器我们也要做相应的配置 如果发送请求的浏览器支持 gzip,就发送给它 gzip格式的文件 我的服务器是用 express框架搭建的 只要安装一下 compression就能使用
// 要放在所有其他中间件注册之前
const compression = require('compression')
app.use(compression())
闭包
闭包是指有权访问另一个函数作用域中的变量的函数;
闭包的特性
看一下这一段的封装,jQuery也采用了类似的封装方式,外部的方法和变量就不会污染闭包内部的东西,同时,闭包内的变量也会有效的保存下来
function person(name) {
// 变量作用域为函数内部,外部无法访问,防止了变量名冲突和污染
var name = '小明';
this.sayName= function() {
alert(name)
}
this.changeName= function(newName) {
name = newName
}
}
// 外部无法访问内部变量
let a = new person()
console.log(a.name) // undefiend
a.changeName('小白')
// 这里修改的name会保存下来
a.sayName() // 小白
由于闭包会常驻内存,使用不当会导致内存溢出。解决方法:手动解除引用,name = null。
关于垃圾回收机制可以看下这两篇博客 blog.csdn.net/zxd10001/ar…
Web前端性能优化——如何有效提升静态文件的加载速度
一、如何优化
用户在访问网页时, 最直观的感受就是页面内容出来的速度,我们要做的优化工作, 也主要是为了这个目标。那么为了提高页面加载(或者渲染)速度呢?一般来说有三个方面:
1、代码逻辑:优秀的代码逻辑结构可以有效减少渲染页面使用的内存和速度(比如虚拟DOM),此方面不在本文讨论范围内。
2、SSR服务器渲染,也就是所谓的“直出”。将首屏所有内容在服务器端渲染成html静态代码后,直接输出给浏览器,可以有效加快用户访问站点时首屏的加载时间。不过此方面也不在本文讨论范围内。
3、提升静态文件的加载速度,这是本文会讨论的点,而这方面大致又可分为下面几点:
— 加快静态文件下载速度
— 减少静态文件的文件大小
— 减少静态文件请求数量,从而减少发起请求的次数(对于移动端页面来说,请求的开销比网速的开销要大)
(一)代码压缩
最常规的优化手段之一。
我们在平时开发的时候,JS脚本文件和CSS样式文件中的代码,都会依据一定的代码规范(比如javascript-standard-style)来提高项目的可维护性,以及团队之间合作的效率。
但是在项目发布现网后, 这些代码是给客户端(浏览器)识别的,此时代码的命名规范、空格缩进都已没有必要,我们可以使用工具将这些代码进行混淆和压缩,减少静态文件的大小
这里我们选择使用Webpack,具体会在后面介绍。
(二)文件合并
1、合并js脚本文件
2、合并css样式文件
3、合并css引用的图片,使用sprite雪碧图。
这里我们继续选择使用Webpack,具体会在后面介绍。
(三)gzip
我们的文件在压缩合并之后,文件大小和文件数量都有了客观的减少。但是一旦站点业务逻辑多了,或者引入的第三方库多了之后,对于移动端来说,文件大小还是不太乐观。
这个时候就是gzip压缩登场的时候啦~我们在webpack的配置中增加gzip压缩配置:
上面代码会对文件大小大于10240,并且压缩率好于0.8的js、css文件进行gzip压缩,执行打包代码后生成结果文件如下:
我们可以看到除了原有的js和css文件外,我们还得到了压缩后的gz文件。
把所有这些文件一起部署到服务器上。(当然也可以直接nginx或其他web server配置gzip压缩)
(四)CDN和缓存
为什么使用CDN?
CDN 是一个全球(或者只有国内,具体看供应商)分布式网络,它把网站内容更快地传递给服务范围内的一个具体位置,而往往这个具体的位置离实际的内容服务器距离很远。举个极端点的例子,你的网站主机在爱尔兰(海南),而你的用户则在澳大利亚(漠河)访问。这时当你的用户访问你的网站的时候,延迟会很大,把你的(静态)数据用 CDN 放到澳大利亚(漠河)则会很大程度上提高用户访问网站的体验。
如果没有CDN服务,我们可以添加Expires头,减少DNS查找(DNS一般指域名系统(服务)协议。域名系统(服务)协议(DNS)是一种分布式网络目录服务,主要用于域名与 IP 地址的相互转换,以及控制因特网的电子邮件的发送。),配置ETag,使AjaX可缓存。
还可参考blog.csdn.net/weixin_3085…
(五)安全方面: CSP
web前端对于xss安全漏洞一定不陌生。我们知道Javascript语句甚至是css表达式都可能导致xss攻击,现在很多前端会使用CSP策略来进行脚本源的限制防御。
而我们由于使用的cdn域名和业务域名不一样:
cdn域名:cdn.xxx.qq.com 业务域名:xxx.qq.com
我们可以:
- 在index.html静态入口文件的meta http-equiv头中做配置;
服务器端直接返回相应的HTTP response header头信息;
例如:
这里除了指定了cdn的域名源,告诉浏览器从这个域名加载的js文件都是可信的。同时因为我们使用的webpack打包压缩代码后的一些特性,我们还需要加上'unsafe-inline'标识。
使用CSP策略我们可以指定浏览器安全解析script、css、fonts、media等资源的源与方式。
二、webpack2.0
使用webpack2最重要的地方就是使用它tree-shaking的特性。这个特性对于ES6的module管理有着非常优美的优化,大概能减少30%左右的包体积。
ES module和CommonJS的require模块管理不同,前者是基于静态的,而后者是动态的。
ES module:
只允许静态同步 import
在模块执行之前,导入和导出已经关联
导入和导出是不可变的
CJS:
允许动态同步 require()
导出仅在模块执行后才知道
导出可以在模块初始化后添加,替换和删除
现在我们来看一下如何使用webpack:
代码压缩
我们自己写的代码因为在开发时需要遵循一定的代码规范,所以会有很多多余的换行和空格字符,甚至是便于阅读的长变量名,这些其实对于机器(浏览器)来说,都不是必要的。所以我们可以把这些都干掉。比如我们写的代码可能是这样的:
接着我们就使用Webpack来进行压缩。首先,需要在工程根目录的package.json(相信使用过npm包管理的前端同学一定不陌生)文件中添加webpack的依赖配置:
各个工程应该按需引入需要的loader和webpack-plugin库。有一点需要注意的是:webpack本身是没有对各个类型的文件进行分析处理的能力的,这个时候我们需要使用各种第三方库的loader,比如css-loader等(当然我们也可以自己编写loader)。同时webpack也有强大的第三方Plugin插件供我们对文件进行进一步处理。
接下来我们就可以在scripts中指向的脚本文件里编写webpack对应的构建代码了。
例如在webpackConfig配置中的plugins属性数组中,我们可以添加以下配置:
而最终生成的文件结构如下:
我们可以看到所有样式代码被压缩后抽离到了一个app.[hash].css文件中,所有js逻辑代码按照业务逻辑和第三方库被抽离到了app.[hash].js和vendor.[hash].js文件中。
被打包文件的内容也已经被webpack压缩混淆,减少了加载文件的Content Size。
关于其他的webpack用法配置,可以查询官方文档和中文文档,这里就不一一详细说明了
目前webpack3 和webpack4使用了新的方式打包代码,可以进一步提升js在浏览器中的执行效率。
三、题外话
跨域方面: CORS
我们知道由于现代浏览器安全策略的不断完善,对跨域请求的限制也是各种各样。
当我们保存在静态资源文件中的script对其他域名发起请求时就会遇到跨域问题,如果没有做任何措施,请求会被浏览器拦截。
当前主流的跨域解决方案主要是JSONP和CORS
由表可见,随着前端不断发展,CORS跨域是大趋势。 CORS需要被请求端根据请求者的host,与白名单比对后返回正确的HTTP response header头信息 。
关于CORS: www.cnblogs.com/ay742936292…
作者原链接https://www.cnblogs.com/wetest/p/7738862.html
ES6中相关(async和await的区别以及它们返回的是什么东西)
vue中的登录拦截
兼容IE9 www.jb51.net/article/138…
vue父子组件的生命周期
1. 加载渲染过程
同步引入时生命周期顺序为: 父组件的beforeCreate、created、beforeMount --> 所有子组件的beforeCreate、created、beforeMount --> 所有子组件的mounted --> 父组件的mounted 总结:父组件先创建,然后子组件创建;子组件先挂载,然后父组件挂载。
若有孙组件呢? 父组件先beforeCreate => created => beforeMount , 然后子组件开始beforeCreate => created => beforeMount ,然后孙组件beforeCreate => created => beforeMount => mounted,孙组件挂载完成了,子组件mounted,父组件再mounted
异步引入时生命周期顺序为: 父组件的beforeCreate、created、beforeMount、mounted --> 子组件的beforeCreate、created、beforeMount、mounted
总结:父组件创建,父组件挂载;子组件创建,子组件挂载。
- 子组件更新过程 父beforeUpdate->子beforeUpdate->子updated->父updated
3.父组件更新过程 父beforeUpdate->父updated
4.销毁过程 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
Vue核心思想:数据驱动、组件化
一,数据驱动
传统的前端数据交互是用Ajax从服务端获取数据,然后操作DOM来改变视图;或者前端交互要改变数据时,又要再来一次上述步骤,而手动操作DOM是一个繁琐的过程且易出错。 Vue.js 是一个提供了 MVVM 风格的双向数据绑定的 Javascript 库,专注于View 层。它让开发者省去了操作DOM的过程,只需要改变数据。Vue会通过Dircetives指令,对DOM做一层封装,当数据发生改变会通知指令去修改对应的DOM,数据驱动DOM变化,DOM是数据的一种自然映射。 Vue还会对操作进行监听,当视图发生改变时,vue监听到这些变化,从而改变数据,这样就形成了数据的双向绑定。 Vue是一种MVVM框架。而DOM是数据的一个种自然映射。传统的模式是通过Ajax请求从model请求数据,然后手动的触发DOM传入数据修改页面。Vue中,Directives对view进行了封装,当model里的数据发生变化是,Vue就会通过Directives指令去修改DOM。同时也通过DOM Listener实现对视图view的监听,当DOM改变时,就会被监听到,实现model的改变,实现数据的双向绑定。
二,组件响应原理
数据(model)改变驱动视图(view)自动更新
当你把一个普通的 JavaScript 对象传给 Vue 实例的 data选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是为什么 Vue 不支持 IE8 以及更低版本浏览器的原因。 用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。这里需要注意的问题是浏览器控制台在打印数据对象时 getter/setter 的格式化并不同,所以你可能需要安装 vue-devtools 来获取更加友好的检查接口。 每个组件实例都有相应的 watcher 实例对象,它会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter被调用时,会通知watcher重新计算,从而致使它关联的组件得以更新。
三,组件化
扩展HTML元素,封装可重用的代码。每一个组件都对应一个ViewModel。页面上每个独立的可视/可交互区域都可以视为一个组件。每个组件对应一个工程目录,组件所需要的各种资源在这个目录下就进维护。页面是组件的容器,组件可以嵌套自由组合形成完整的页面。
组件化实现了扩展HTML元素,封装可用的代码。页面上每个独立的可视/可交互区域视为一个组件;每个组件对应一个工程目录,组件所需要的各种资源在这个目录下就近维护;页面不过是组件的容器,组件可以嵌套自由组合形成完整的页面。
原文链接:blog.csdn.net/weixin_4512…
将数组扁平化并去除其中重复的数据,最终得到了一个升序且不重复的数据
var arr=[[1,2,3],[3,4,5,6],[6,7,8,9,[11,12,13,[14]]],10]
利用ES6语法
Array.fromy(从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。)、new Set()数组去重、arr.flat() 数组扁平化 sort()排序
const newArr = Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{return a-b})
数组去重的方法
[...new Set(arr)] ES6语法
call、apply、bind区别
bind语法:
func.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg 当绑定函数被调用时,该参数会作为原函数运行时的this指向。当使用new 操作符调用绑定函数时,该参数无效。
arg1, arg2, ... 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
call语法:
fun.call(thisArg, arg1, arg2, ...)
thisArg::在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。
arg1, arg2, ... 指定的参数列表。
apply语法:
fun.apply(thisArg, [argsArray])
thisArg: 在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。
argsArray: 一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。