前端面试题总结
一.简述前端构建工具。fis3,Gulp,Grunt,Webpack
www.tuicool.com/articles/beU7736
答:
(1)类是任务管理工具(task runner)。通过声明和组合构建任务来进行整个网站的构建, 有自己的一套任务声明语法和任务实现接口。例如Grunt和Gulp,这两个都是插件式的架构。有大量的插件可用,缺点就在于做什么都只能用插件,没有就自己写一个。
(2)类是打包工具(package tool)。通过为每一类文件配置需要的处理方式,来实现整个站点的构建。如Webpack和FIS,这两个都是整个站点的整体构建解决方案。fis3的使用方法见blog.csdn.net/lululove19870526/article/details/49891253
(3)类是构建工具(build tool)。比如Make。
详细介绍:
Webpack:Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块,比如 CommonJs 模块、 AMD 模块、 ES6 模块、CSS、图片、 JSON、Coffeescript、 LESS 等。
webpack的优点如下:
1. webpack遵循commonJS的形式,但对AMD/CMD的支持也很全面,方便旧项目进行代码迁移。
2.能被模块化的不仅仅是JS,所有的静态资源,例如css,图片等都能模块化,即以require的方式引入。
3.开发便捷,能替代部分grunt/gulp的工作,比如打包、压缩混淆、图片转base64等。
Grunt:grunt是一套前端自动化工具,一个基于nodeJs的命令行工具,一般用于:压缩文件,合并文件,简单语法检查。
Grunt的优点如下:
Grunt生态系统非常庞大,并且一直在增长。由于拥有数量庞大的插件可供选择,因此,你可以利用Grunt自动完成任何事,并且花费最少的代价。如果找不到你所需要的插件,那就自己动手创造一个Grunt插件,然后将其发布到npm上吧
Gulp:基于流的自动化构建工具。文件的压缩打包合并,是一个纯粹的工具,并不能将你的css等非js资源模块化,通过代码优于配置的策略,Gulp 让简单的任务简单,复杂的任务可管理。
构建快速
利用 Node.js 流的威力,你可以快速构建项目并减少频繁的 IO 操作。
插件高质
Gulp 严格的插件指南确保插件如你期望的那样简洁高质得工作。
易于学习
通过最少的 API,掌握 Gulp 毫不费力,构建工作尽在掌握:如同一系列流管道
二.sass和less有什么区别?
答:
1.编译环境不一样
Sass的安装需要Ruby环境,是在服务端处理的,而Less是需要引入less.js来处理Less代码输出css到浏览器,也可以在开发环节使用Less,然后编译成css文件,直接放到项目中。
2.变量符不一相,less是@,而scss是$,而且它们的作用域也不一样,less是块级作用域
3.输出设置,Less没有输出设置,sass供4种输出选项,nested,compact,compressed和expanded
nested:嵌套缩进的css代码(默认)
expanded:展开的多行css代码 compact:简洁格式的css代码 compressed:压缩后的css代码
4.sass支持条件语句,可以使用if{}else{},for{}循环等等,而less不行
5.引用外部css文件,sass引用外部文件必须以_开头,文件名如果以下划线_形状,sass会认为该文件是一个引用文件,不会将其编译为css文件。less引用外部文件和css中的@import没什么差异。
6.sass和less的工具库不同。sass有工具库Compass,简单说,sass和Compass的关系有点像Javascript和jQuery的关系,Compass是sass的工具库。在它的基础上,封装了一系列有用的模块和模板,补充强化了sass的功能。less有UI组件库Bootstrap,Bootstrap是web前端开发中一个比较有名的前端UI组件库,Bootstrap的样式文件部分源码就是采用less语法编写。
总结:不管是sass,还是less,都可以视为一种基于CSS之上的高级语言,其目的是使得CSS开发更灵活和更强大,sass的功能比less强大,基本可以说是一种真正的编程语言了,less则相对清晰明了,易于上手,对编译环境要求比较宽松。考虑到编译sass要安装Ruby,而Ruby官网在国内访问不了,个人在实际开发中更倾向于选择less
三.sessionStorage和localstroage与cookie之间有什么关联和区别,cookie最大存放多少字节
答:
三者共同点:都是保存在浏览器端,且同源的。
1、cookie在浏览器和服务器间来回传递。而sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
2、存储大小限制也不同,cookie数据不能超过4k,sessionStorage和localStorage但比cookie大得多,可以达到5M
3、数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭
4、作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面(即数据不共享);localStorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的(即数据共享)。
四.前端开发的优化问题
答:
(1) 减少http请求次数:CSS Sprites, JS、CSS源码压缩、图片大小控制合适;网页Gzip,CDN托管,data缓存 ,图片服务器。
(2) 前端模板 JS+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量,不用请求,减少请求次数
(3) 用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能
(4) 用setTimeout来避免页面失去响应
(5) 用hash-table来优化查找
(6) 当需要设置的样式很多时设置className而不是直接操作style
(7) 少用全局变量,缓存DOM节点查找的结果
(8) 缓存DOM节点查找的结果
(9) 避免使用CSS Expression(css表达式)又称Dynamic properties(动态属性)
(10) 图片预加载,将样式表放在顶部,将脚本放在底部加上时间戳。
(11) 避免在页面的主体布局中使用table,table要等其中的内容完全下载之后才会显示出来,显示比div+css布局慢
请说出三种减低页面加载时间的方法
1、压缩css、js文件
2、合并js、css文件,减少http请求
3、外部js、css文件放在最底下
4、减少dom操作,尽可能用变量替代不必要的dom操作
五.浏览器内核问题和兼容问题
关于浏览器内核
主要分成两部分:渲染引擎(layout engineer或Rendering Engine)和JS引擎。
渲染引擎:负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入CSS等),以及计算网页的显示方式,后会输出至显示器或打印机。浏览器的内核的不同对于网页的语法解释会有不同,所以渲染的效果也不相同。所有网页浏览器、电子邮件客户端以及其它需要编辑、显示网络内容的应用程序都需要内核。
JS引擎则:解析和执行javascript来实现网页的动态效果。
最开始渲染引擎和JS引擎并没有区分的很明确,后来JS引擎越来越独立,内核就倾向于只指渲染引擎。
谈谈浏览器的内核,并且说一下什么是内核?
Trident (['traɪd(ə)nt])--IE,Gecko (['gekəʊ])--Firefox, Presto (['prestəʊ])--opera,webkit—谷歌和Safari
浏览器内核又可以分成两部分:渲染引擎和 JS 引擎。它负责取得网页的内容(HTML、XML、图像等等)、整理讯息(例如加入 CSS 等),以及计算网页的显示方式,然后会输出至显示器或打印机。JS 引擎则是解析 Javascript 语言,执行 javascript 语言来实现网页的动态效果。
写出几种IE6 BUG的解决方法
1.双边距BUG float引起的 使用display
2.3像素问题 使用float引起的 使用dislpay:inline -3px
3.超链接hover 点击后失效 使用正确的书写顺序 link visited hover active
4.Ie z-index问题 给父级添加position:relative
5.Png 透明 使用js代码 改
6.Min-height 最小高度 !Important 解决’
7.select 在ie6下遮盖 使用iframe嵌套
8.为什么没有办法定义1px左右的宽度容器(IE6默认的行高造成的,使用over:hidden,zoom:0.08 line-height:1px)
六.关于Ajax的面试题
ajax 兼容性 浏览器内核 请求之后的结果状态(状态码) 数据转换 json数据转换 对象 构造函数,原型链,闭包 缓存cooks。
1.什么是ajax:
异步javascript和XML,是指一种创建交互式网页应用的网页开发技术。通过后台与服务器进行少量数据交换,AJAX可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。
2.判断AJAX浏览器是否支持
例子解释:首先声明一个保存 XMLHttpRequest 对象的 xmlHttp 变量。
然后使用 XMLHttp=new XMLHttpRequest() 来创建此对象。这条语句针对 Firefox、Opera 以及 Safari 浏览器。假如失败,则尝试针对 Internet Explorer 6.0+ 的 xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"),假如也不成功,则尝试针对 Internet Explorer 5.5+ 的 xmlHttp=new ActiveXObject("Microsoft.XMLHTTP")。
答:第一步,创建ajax对象 var xxx = new XMLHttpRequest();
第二部,判断数据传输方式(GET / POST)
第三部,绑定请求地址,打开链接open。 即 open(method,url,async);
第四步,发送send。即开始请求 send(string) string:仅用于 POST 请求
第五步,获取请求结果。
(4)xhr对象status ? readystate?readystate 0~4?说出几个http协议状态码? 200 201 302 304 400 404 500?
答:
1.
status是XMLHttpRequest对象的一个属性,表示响应的HTTP状态码。readyState是XMLHttpRequest对象的一个属性,用来标识当前XMLHttpRequest对象处于什么状态。
2.
0:未初始化状态:此时,已经创建了一个XMLHttpRequest对象
1: 准备发送状态:此时,已经调用了XMLHttpRequest对象的open方法,并且XMLHttpRequest对象已经准备好将一个请求发送到服务器端
2:已经发送状态:此时,已经通过send方法把一个请求发送到服务器端,但是还没有收到一个响应
3:正在接收状态:此时,已经接收到HTTP响应头部信息,但是消息体部分还没有完全接收到
4:完成响应状态:此时,已经完成了HTTP响应的接收
3.
200:请求成功
201:请求成功并且服务器创建了新的资源
302:服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来响应以后的请求。
304:自从上次请求后,请求的网页未修改过。服务器返回此响应时,不会返回网页内容。
400:服务器不理解请求的语法
404:请求的资源(网页等)不存在
500: 内部服务器错误
(5)如何处理ajax请求之后后台传过来的数据
在上面我们能看见初步获取了 str,即获取到后台来的数据,有时候后台在数据发过来之前就进行过处理,我们 JS 获取到就是对象,这样就很简单省事了。但是有时候后台人员直接传过来的是字符串形式,这样就需要我们苦逼的前端去处理一下数据了。然后问题就来了我们该怎么去处理字符串,哪种处理方式更好;
目前js处理有两种:1、eval()。2、JSON.parse();那么这两种有什么区别呢?
注意:eval()的功能是把对应的字符串解析成JS代码并运行;应该避免使用eval,不安全,非常耗性能(2个步骤,一次解析成js语句,一次执行)
(6)ajax缓存原理
ajax的缺点
1、ajax不支持浏览器back按钮。
2、安全问题AJAX暴露了与服务器交互的细节。
3、对搜索引擎的支持比较弱。
4、破坏了程序的异常机制。
(7)ajax请求方式有几种
如果你指定了 dataType 选项,请确保服务器返回正确的 MIME 信息,(如 xml 返回"text/xml")。
实例:
保存数据到服务器,成功时显示信息。
$.ajax({
type:"post",
dataType:"html",
url:'/Resources/GetList.ashx',
data: dataurl,
success: function (data) {if(data !="") {
$("#pager").pager({ pagenumber: pagenumber, pagecount: data.split("$")[1], buttonClickCallback: PageClick });
$("#anhtml").html(data.split("$")[0]);
}
}
});
(8)ajax和jsonp
答:
相同点:都是请求一个url
不同点:ajax的核心是通过xmlHttpRequest获取内容
jsonp的核心则是动态添加<script>标签来调用服务器,提供的js脚本标签来调用服务器 供的js脚本。
标签来调用服务器提供的js脚本标签来调用服务器提供的js脚本标签来调用服务器提供的js脚本。
标签来调用服务器 供的js脚本。
(9)关于跨域问题
blog.csdn.net/joyhen/article/details/21631833
答:(1)jsonp是用script标签的src属性是不跨域的这一性质,所以其实是封装了这个功能而已,jquery会创建一个script标签,把src的地址指向后端,src会带一个callback参数,一般是一个函数名,后端根据这个请求,获取参数,然后把需要返回的数据包裹在这个函数内,前端获得了这些js代码,就会执行这个callback,自然就把数据传到客户端了。只支持GET请求参考文档
(2)cors(cross-origin resource sharing)就是服务端加上一句 header(“Access-Control-Allow-Origin:*”); 支持所有请求,但是兼容性不太好,支持IE8+,chrome3+。 (3)window.name.一个窗口window的生命周期内,窗口载入的页面共享一个window.name,每个页面都有读写权限, data.html里面就写上window.name=”data..”;然后在a.html里用一个隐藏的iframe载入data.html,然后在a.html里用js把iframe的src设为同源的一个页面。
(4)修改document.domain的方法只适用于不同子域的框架间的交互。比如http://www.example.com/a.html和 http:example.com/b.html 在两个页面中都修改document.domain为”example.com”
(5)img标签的src也是不跨域的,所以可以
img.src=“http://example.com/data?value=123。
但是这种方法只能用来发送请求.
(6)HTML5有一个postMessage(data,origin)方法,可以向当前页面中的iframe或者当前页弹出的窗口发送消息
1,jsonp
2,PHP端修改header 利用CORS
3,代理:
例如www.123.com/index.html需要调用www.456.com/server.php,可以写一个接口www.123.com/server.php,由这个接口在后端去调用www.456.com/server.php并拿到返回值,然后再返回给index.html,这就是一个代理的模式。相当于绕过了浏览器端,自然就不存在跨域问题。
4,document.domain + iframe (只有在主域相同的时候才能使用该方法)
问题:
1、安全性,当一个站点被攻击后,另一个站点会引起安全漏洞。
2、如果一个页面中引入多个iframe,要想能够操作所有iframe,必须都得设置相同domain。
5.window.name + iframe
window.name 的美妙之处:name 值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)。
1) 创建a.com/cs1.html
2) 创建a.com/proxy.html,并加入如下代码
6.web sockets
七.关于HTTP的问题总结 :(http://www.360doc.com/content/10/0930/17/3668821_57590979.shtml)
(osi七种模型介绍 https://www.zybang.com/question/f05fd53d632bfa9dd5fef66552234c84.html?ssl=1)
一个页面从输入URL到页面加载显示完成,这个过程中都发生了什么?
这个过程可以分为四个步骤:
1.当发送一个URL请求时,不管这个URL是web页面的URL还是web页面的每个资源的URL,浏览器都会开启一个线程来处理这个请求,同时在远程DNS服务器上启动一个DNS查询,这样就可以使得浏览器获得请求对应的IP地址了。
2.浏览器通过与远程web服务器TCP三次握手协商来建立一个TCP/IP链接。三个握手包含一个同步报文,一个同步-应答报文和一个应答报文,这三个报文在浏览器和服务器之间进行传递,该握手首先由客户端尝试建立起通信,而后服务器应答并接受客户端的请求,最后由由客户端发出该请求已经被接受的报文。
3.一旦TCP/IP链接建立,浏览器会通过该链接向远程服务器发送HTTP的GET请求。远程服务器找到资源并使用HTTP响应返回该资源,值为200的HTTP状态码表示一个正确的响应。
4.此时,web服务器提供资源服务,客户端开始下载资源。
简单来说,浏览器会解析HTML生成DOM tree,其次会根据CSS生成CSS rule tree,而javascript又可以根据DOM api操作DOM
在这里再归纳下http状态吗有哪些?它们分别代表什么意思?
要熟悉前后端的通信流程,最好把动态网站的背后细节也介绍一遍
八.AMD,CMD,CommonJS以及RequireJS和SeaJS的个人感悟
AMD 是 RequireJS 在推广过程中对模块定义的规范化产出。
CMD 是 SeaJS 在推广过程中对模块定义的规范化产出。
类似的还有 CommonJS Modules/2.0 规范,是 BravoJS 在推广过程中对模块定义的规范化产出。
这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的。
目前这些规范的实现都能达成浏览器端模块化开发的目的。
AMD与CDM的区别:
1.对于于依赖的模块,AMD 是提前执行(好像现在也可以延迟执行了),CMD 是延迟执行。
2.AMD 推崇依赖前置,CMD 推崇依赖就近。
3.AMD 推崇复用接口,CMD 推崇单用接口。
4.书写规范的差异,不具体说明了。
1. 对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。
不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.
2. CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b') // 依赖可以就近书写
b.doSomething()
// ...
})
// AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
})
虽然 AMD 也支持 CMD 的写法,同时还支持将 require 作为依赖项传递,但 RequireJS 的作者默认是最喜欢上面的写法,也是官方文档里默认的模块定义写法。
3. AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。
4. 还有一些细节差异,具体看这个规范的定义就好,就不多说了。
另外,SeaJS 和 RequireJS 的差异,可以参考
执行模块的机制大不一样
-----------------------------------
由于 RequireJS 是执行的 AMD 规范, 因此所有的依赖模块都是先执行.
使用 RequireJS 默认定义模块的方式, 在理解上会更清楚一些, 但个人还是偏爱 require('./mod1') 这样的方式
define(['dep1', 'dep2'], function (dep1, dep2) {
//Define the module value by returning a value.
return function () {};
});
SeaJS 和 RequireJS 的差异
SeaJS只会在真正需要使用(依赖)模块时才执行该模块
SeaJS是异步加载模块的没错, 但执行模块的顺序也是严格按照模块在代码中出现(require)的顺序
而RequireJS会先尽早地执行(依赖)模块, 相当于所有的require都被提前了, 而且模块执行的顺序也不一定100%就是先mod1再mod2
因此你看到执行顺序和你预想的完全不一样! 颤抖吧~ RequireJS!
CommonJS:就是用来规范JS的使用的,主要为了JS在后端的表现制定的,不太适合前端。它定了三个模块:模块引用的require,模块定义的exports和模块标识module。CommonJS是一种规范,包括很多内容,NodeJS是这种规范的实现。
RequireJS与SeaJS 都是模块加载器。RequireJS工作于web浏览器端,同时也工作于web服务器端,SeaJS专注于web浏览器端。
网站:1 www.cnblogs.com/jackyWHJ/articles/4943271.html
入门requirejs http://www.runoob.com/w3cnote/requirejs-tutorial-2.html
异步加载的方式有哪些?
方案一:标签的async="async"属性(详细参见:script标签的async属性)
方案二:标签的defer="defer"属性标签的defer="defer"属性方案三:动态创建标签方案四:AJAX eval(使用AJAX得到脚本内容,然后通过eval_r(xmlhttp.responseText)来运行脚本)方案五:iframe方式
方案三:动态创建标签
方案四:AJAX eval(使用AJAX得到脚本内容,然后通过eval_r(xmlhttp.responseText)来运行脚本)
方案五:iframe方式
类型九:对于线程·和进程的理解
操作系统的设计,因此可以归结为三点:
(1)以多进程形式,允许多个任务同时运行;
(2)以多线程形式,允许单个任务分成不同的部分运行;
(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。
3.区别
进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。
1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
2) 线程的划分尺度小于进程,使得多线程程序的并发性高。
3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
4)线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5)从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
4.优缺点
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
类型十:关于Jquery
1.jquery 中如何将数组转化为json字符串,然后再转化回来?
jQuery中没有提供这个功能,所以你需要先编写两个jQuery的扩展:
$.fn.stringifyArray = function(array) {
return JSON.stringify(array)
}
$.fn.parseArray = function(array) {
return JSON.parse(array)
}
然后调用:
$("").stringifyArray(array)
2.jQuery中.bind() .live() .delegate() .on()的区别
类型十一:关于js
1.说说你对this的理解?
在JavaScript中,this通常指向的是我们正在执行的函数本身,或者是,指向该函数所属的对象。
全局的this → 指向的是Window
函数中的this → 指向的是函数所在的对象
对象中的this → 指向其本身
2.继承的几种方式 www.cnblogs.com/humin/p/4556820.html
1.原型链继承
2.借用构造函数继承
3.组合继承(原型+借用构造)
4.原型式继承
5.寄生式继承
6.寄生组合式继承
构造函数.prototype= 原型对象
原型对象.constructor = 构造函数(模板)
原型对象.isPrototypeof(实例对象) 判断实例对象的原型 是不是当前对象
3.关于事件
(1)关于事件,IE与火狐的事件机制有什么区别? 如何阻止冒泡?
[1].在IE中,事件对象是作为一个全局变量来保存和维护的.所有的浏览器事件,不管是用户触发的,还是其他事件,都会更新window.event对象.所以在代码中,只要调用window.event就可以获取事件对象, 再event.srcElement就可以取得触发事件的元素进行进一步处理.
[2].在FireFox中,事件对象却不是全局对象,一般情况下,是现场发生,现场使用,FireFox把事件对象自动传给事件处理程序.
关于事件的兼容性处理要熟练掌握,事件对象具体哪些属性存在兼容性问题,IE与标准事件模型事件冒泡与事件捕获的支持要理解
(2)如何阻止事件冒泡和默认事件?
阻止浏览器的默认行为
window.event?window.event.returnValue=false:e.preventDefault();
停止事件冒泡
window.event?window.event.cancelBubble=true:e.stopPropagation();
原生JavaScript中,return false;只阻止默认行为,不阻止冒泡,jQuery中的return false;既阻止默认行为,又阻止冒泡
4.关于window对象(event,navigator,history,location)
关于history(通过history.pushState无刷新改变url)
http://www.myexception.cn/web/1955044.html
在浏览器中改变地址栏url,将会触发页面资源的重新加载,这使得我们可以在不同的页面间进行跳转,得以浏览不同的内容。但随着单页应用的增多,越来越多的网站采用ajax来加载资源。因为异步加载的特性,地址栏上的资源路径没有被改变,随之而来的问题就是页面的状态无法被保存。这导致我们难以通过熟悉的方式(点击浏览器前进/后退按钮),在前后的页面状态间进行切换。
为了解决ajax页面状态不能返回的问题,人们想出了一些曲线救国的方法,比如利用浏览器hash的特性,将新的资源路径伪装成锚点,通过onhashchange事件来改变状态,同时又避免了浏览器刷新。但这样始终显得有些hack。
现在HTML5规范为window.history引入了两个新api,pushState和replaceState,我们可以使用它很方便的达到改变url不重载页面的目的
#hash最后再来介绍另一种无刷新技巧window.location.hash的使用。
URL中#称为位置的标识符,代表网页中的一个位置,当浏览器读取这个URL后,会自动将可视区域滚动至所定义的锚点处。HTTP请求中不包括#,也就是说改变#后的内容不会向服务器发起请求,因此也就不会引起页面重载。
window.location.hash这个属性可读可写。读取时,可以用来判断网页状态是否改变;写入时,则会在不重载网页的前提下,创造一条访问历史记录。
当#值发生变化时,就会触发onhashchange事件。