键盘事件
keydown
:在键盘上按下某个键时触发。如果按住某个键,会不断触发该事件,但是 Opera 浏览器不支持这种连续操作。该事件处理函数返回 false 时,会取消默认的动作(如输入的键盘字符,在 IE 和 Safari 浏览器下还会禁止keypress 事件响应)。keypress
:按下某个键盘键并释放时触发。如果按住某个键,会不断触发该事件。该事件处理函数返回 false 时,会取消默认的动作(如输入的键盘字符)。keyup
:释放某个键盘键时触发。该事件仅在松开键盘时触发一次,不是一个持续的响应状态。keydown
可以响应任一键盘按键但是无法区分字母的大小写,所以一般用keypress
检测字符串类按键,keypress
只能响应字符类按键。
// ASCⅡ码转换对应字符
document.onkeypress = function(e){
console.log(String.fromCharCode(e.charCode));
}
- 键盘事件的应用(运动方块)
var div = document.createElement("div");//在页面里写入div
document.body.appendChild(div);//把div放入HTML里
div.style.width = '100px';
div.style.height = '100px';
div.style.backgroundColor = '#8c8c';
div.style.position = 'absolute';
div.style.left = '0';
div.style.top = '0';
//敲击键盘上下左右产生效果
var btn = document.getElementsByTagName('button')[0];
var speed = 5;
btn.onclick = function(){
speed ++;
}
document.onkeydown = function (e) {
switch (e.which) {
case 38://上
div.style.top = parseInt(div.style.top) - speed + 'px';
break;
case 40://下
div.style.top = parseInt(div.style.top) + speed + 'px';
break;
case 37://左
div.style.left = parseInt(div.style.left) - speed + 'px';
break;
case 39://右
div.style.left = parseInt(div.style.left) + speed + 'px';
break;
}
}
键盘响应顺序
-
当按下键盘时,会连续触发多个事件,它们将按如下顺序发生:
-
对于字符键来说,键盘事件的响应顺序:keydown → keypress → keyup。
-
对于非字符键(如功能键或特殊键)来说,键盘事件的相应顺序:keydown → keyup。
-
如果按下字符键不放,则 keydown 和 keypress 事件将逐个持续发生,直至松开按键。
-
如果按下非字符键不放,则只有 keydown 事件持续发生,直至松开按键。
json
json
本质是一个对象,但是用法有一定的区别,对象用于本地,json用于传输。
//json基本格式
var obj = {
"name" : "deng",
"age" : 132
}
JSON.stringify(obj);
- 前端与后台互相传输的是字符串
JSON.stringify
json–>stringJSON.parse
string–>json
浏览器的运行机制
- 构建
DOM
树(parse):渲染引擎解析HTML文档,首先将标签转换成DOM
树中的DOM node
(包括js生成的标签)生成内容树(Content Tree/DOM Tree); - 构建渲染树(construct):解析对应的
CSS
样式文件信息(包括js生成的样式和外部css文件),而这些文件信息以及HTML
中可见的指令(如<b></b>
),构建渲染树(Rendering Tree/Frame Tree); - 布局渲染树(reflow/layout):从根节点递归调用,计算每一个元素的大小、位置等,给出每个节点所应该在屏幕上出现的精确坐标;
- 绘制渲染树(paint/repaint):遍历渲染树,使用UI后端层来绘制每个节点。
重绘和重排
- 绘制:当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈现在页面上。
- 重绘(repaint或redraw):重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。(触发重绘的条件:改变元素外观属性。如:
color
,background-color
等。) - 重排(重构/回流/reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候。
- 重绘和重排的关系:在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。所以,重排必定会引发重绘,但重绘不一定会引发重排。
- 触发重排的条件:任何页面布局和几何属性的改变都会触发重排,比如:
1、页面渲染初始化;(无法避免)
2、添加或删除可见的DOM元素;
3、元素位置的改变,或者使用动画;
4、元素尺寸的改变——大小,外边距,边框;
5、浏览器窗口尺寸的变化(resize事件发生时);
6、填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变;
7、读取某些元素属性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) ) - 重绘重排的代价:耗时,导致浏览器卡慢。
- 优化:
我们要减少重绘和重排就是要减少对渲染树的操作,则我们可以合并多次的DOM和样式的修改。并减少对style样式的请求。
(1)直接改变元素的className
(2)display:none;先设置元素为display:none;然后进行页面布局等操作;设置完成后将元素设置为display:block;这样的话就只引发两次重绘和重排;
(3)不要经常访问浏览器的flush队列属性;如果一定要访问,可以利用缓存。将访问的值存储起来,接下来使用就不会再引发回流;
(4)使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;
(5)将需要多次重排的元素,position属性设为absolute或fixed,元素脱离了文档流,它的变化不会影响到其他元素;
(6)如果需要创建多个DOM节点,可以使用DocumentFragment创建完后一次性的加入document;
(7)尽量不要使用table布局
异步加载
js加载
- js加载的缺点:会阻止浏览器的后续处理,停止后续的解析,只有当当前加载完成,才能进行下一步操作。所以默认同步执行才是安全的。但这样如果js中有输出document内容、修改dom、重定向等行为,就会造成页面堵塞。所以一般建议把
<script>
标签放在<body>
结尾处,这样尽可能减少页面阻塞。
异步加载
- 作用:异步加载又叫非阻塞加载,浏览器在下载执行js的同时,还会继续进行后续页面的处理。主要有三种方式。
defer
只有IE能用。
<script type="text/javascript" src ="tools,js" defer></script>
async
加载完成就执行,只能加载外部脚本。
<script type="text/javascript" src ="tools,js" async></script>
callback()
function a(callback){
alert('parent');
alert('callback');
callback();
}
function b(){
alert('b');
}
a(b);
js加载时间线
1.创建document对象,开始解析web页面。解析html元素和他们支持的文本内容后,添加element对象和text节点到文档中,这个节点document.readyState=“loading”。
2.遇到link外部css,创建线程加载,并继续解析文档。
3.遇到script外部js,并且没有设置async,defer.(同步加载)浏览器加载并阻塞,等待js加载完成并执行该脚本,然后继续解析文档。
4.遇到script外部js,并且设置有async,defer(异步加载),浏览器创建线程加载,并继续解析文档。对于async属性的脚本,脚本加载完成后立即执行。(异步禁止使用document.write()
原因是: 相当于html文档输出到页面,当整个文档解析差不多的时候,再调用document.write()方法的时候,它将之前的所有文档流清空,将当前的文档流输出
例:window.οnlοad=function(){} 该方法是页面所有加载并且所有文档解析完毕后,然后加载调用该方法,就会将之前的文档流全部清空)
5.遇到img等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档。
6.当文档解析完成(domtree刚建立完),document.readyState=“interactive”;
7.文档解析完成后,所有设置defer的脚本会按照顺序执行。(注意与ansyc的不同,但同样机制使用document.write())
8.document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段。
9.当所有的async的脚本加载完成并执行后,img等加载完成后,document.readyState=“complete”,window对象触发load事件。
10.从此,以异步响应方式处理用户输入,网络事件等。
-
总结三句话:
1.创建document文档对象
2.文档解析完
3.加载完,再执行完
正则表达式
创建方法
- 直接量
//正则表达式的创建1
var reg = /abc/;// /abc/加i(ignoreCase)忽视大小写;g(gobal)全局匹配可以找出多个abc片段(用str.match(reg)查找)
var str = 'abcde';
console.log(reg.test(str));//测试str里面含不含有abc,含有返回true
new RegExp()
// 正则表达式的创建2
var str = 'abcde';
var reg = new RegExp('abc','i');//第一个参数放规则,第二个放修饰符
console.log(reg.test(str));
var reg = /abc/i;
var reg1 = new RegExp(reg);//完全一样的两个正则表达式,互相独立
描述字符范围
- 在正则表达式语法中,放括号表示字符范围。在方括号中可以包含多个字符,表示匹配其中任意一个字符。如果多个字符的编码顺序是连续的,可以仅指定开头和结尾字符,省略中间字符,仅使用连字符~表示。如果在方括号内添加脱字符^前缀,还可以表示范围之外的字符。例如:
- [abc]:查找方括号内任意一个字符。
- [^abc]:查找不在方括号内的字符。
- [0-9]:查找从 0 至 9 范围内的数字,即查找数字。
- [a-z]:查找从小写 a 到小写 z 范围内的字符,即查找小写字母。
- [A-Z]:查找从大写 A 到大写 Z 范围内的字符,即查找大写字母。
- [A-z]:查找从大写 A 到小写 z 范围内的字符,即所有大小写的字母。
选择匹配
选择匹配类似于JavaScript
的逻辑与运算,使用竖线|
描述,表示在两个子模式的匹配结果中任选一个。例如:
var r = /\w+|\d+/;
var r1 = /(abc)|(efg)|(123)|(456)/;
重复匹配
在正则表达式语法中,定义了一组重复类量词,如表所示。它们定义了重复匹配字符的确数或约数。
量词 | 描述 |
---|---|
n+ | 匹配任何包含至少一个 n 的字符串 |
n* | 匹配任何包含零个或多个 n 的字符串 |
n? | 匹配任何包含零个或一个 n 的字符串 |
n{x} | 匹配包含 x 个 n 的序列的字符串 |
n{x,y} | 匹配包含最少 x 个、最多 y 个 n 的序列的字符串 |
n{x,} | 匹配包含至少 x 个 n 的序列的字符串 |
//如果仅匹配单词 ggle 和 gogle,可以设计:
var s = "ggle gogle google gooogle goooogle gooooogle goooooogle gooooooogle goooooooogle";
var r = /go{0,1}gle/g;
var a = s.match(r);
//或者
var r = /go?gle/g;
var a = s.match(r);
//如果匹配第 4 个单词 gooogle,可以设计:
var r = /go{3}le/;
var a = s.match(r);