1、javascript中的委托事件
基本概念
事件委托,简单地说,就是把一个元素的响应事件委托给另一个元素。
事件冒泡
事件委托的本质是利用事件冒泡机制。
在document.addEventListener的时候设置事件模型:事件冒泡、事件捕获,一般来说都是使用事件冒泡的。
事件冒泡:事件从最底层逐层向最外层(根元素)传播,通常用document.addEventListener(‘click’,function(){},false)来监听事件;
事件捕获:简单来讲就是从最外层到最底层(目标事件)传播,通常用document.addEventListener(‘click’,function(){},true)来监听事件;
目标阶段:目标阶段就是指事件响应到触发事件的最底层元素上,遵循谁先注册谁执行原则。
事件委托的使用场景
当有大量类似元素需要批量添加事件监听时,使用事件委托可以减少内存开销;
当有动态元素节点上树时,使用事件委托可以让新上树的元素也具有事件监听。
使用事件委托时的注意事项
onmouseenter和onmouseover都表示“鼠标进入”,它俩有什么区别呢?
onmouseenter是不冒泡的,onmouseover是冒泡的。
使用事件委托的优缺点
优点:
- 可以节省大量内存,减少事件注册;
- 可以进行动态绑定,当需要新增子对象时,无需再对其进行事件绑定。 缺点:
如果把所有事件都用事件绑定,可能会出现事件误判,即本来不需要被触发的事件被绑定上了事件。
2、页面优化有哪些方法?
css
- 合并重复的css文件,减少HTTP请求数量
- 从页面中剥离js和css文件
- 将css文件放到页面最上方
- 删除空的css规则
- 优化选择器嵌套,尽量避免层级过深
- 提取公共样式,减少代码的书写
- 充分利用css的继承属性,减少代码量
- 当属性值为0时,不加单位
- 当属性值是小于1的小数时,省略小数点前面的0
- 使用CSS Sprites(精灵图)将多张照片拼接成一张图片,通过CSS background属性来访问图片内容
js
- 减少DOM元素的数量
- 节流、防抖
- 使用图片懒加载(data-src)
- 长列表滚动到可视化区域动态加载(大数据渲染)
- 使用闭包时,在函数结尾处手动删除不需要的局部变量,尤其在缓存dom节点的情况下
- DOM操作优化
-
- 批量添加dom元素时,可先createElement创建并添加节点,最后一次性加入dom
-
- 批量绑定事件,使用事件委托绑定父节点实现,利用了事件冒泡机制
-
- 情况允许的话,使用innerHTML代替appendChild
-
- 在DOM操作时添加样式时尽量增加class属性,而不是通过style样式,减少重排(reflow)
3、Cookie、localStorage和sessionStor有什么区别?
基本概念
Cookie:本意为“小饼干”,它的存储容量非常小,通常只有4KB,主要用于存储用户登录浏览器的一些用户名密码等信息。
localStorage:意为本地存储,是HTML5中新增的一个新技术,对于多数浏览器来说都是兼容的,localStorage可以长时间存储数据,即生命周期是永久性的,即使用户刷新页面或者是关闭浏览器也不能清除数据,除非用户自己主动清除数据,主要用于存储各种信息。
sessionStorage:会话存储,顾名思义,存储在会话窗口的数据。比如在浏览器界面,当用户刷新页面时,sessionStorage存储的数据并不会失效,当用户关闭浏览器时存储的数据才会消失。
总结
| 特性 | Cookie | localStorage | sessionStorage | | :------:| :------: | :------: | | :------: | | 数据的生命周期 | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 永久性的,除非被清除,否则永久保存 | 当用户刷新页面时,数据不会失效。只有关闭浏览器,存储的数据才会清除 | | 存储数据的大小 | 4KB左右 | 一般为5MB | 一般为5MB | | 与服务器端通信 | 每次都会携带在HTTP头中,发送给服务端。但是使用cookie保存过多数据会影响它的性能 | 仅在客户端(即浏览器)中保存,不和服务器通信 | 同localStorage |
4、什么是子选择器?什么是后代选择器?
子选择器
大于号 > 代表子选择器,如div>span,表示获取div的子标签span,
<div>
<span>子span</span>
<span>子span</span>
<span>子span</span>
<p>
<span>后代span</span>
</p>
</div>
div>span{
color: red;
}
后代选择器
空格 代表后代选择器,如div span,表示获取div标签内的所有span标签
<div>
<span>子span</span>
<span>子span</span>
<span>子span</span>
<p>
<span>后代span</span>
</p>
</div>
div span{
color: red;
}
5、什么是闭包?
闭包定义
闭包指的是一个函数可以访问另一个函数作用域中的变量。
内嵌函数可以访问定义在外层函数中的所有变量和函数,还包括外层函数能访问的所有变量和函数。但是在此函数外部却不能访问此函数的内部变量和嵌套函数。
var a=1;
function aaa(){
var b=2;
return function ccc(){
console.log(a);//1
}
}
console.log(b);// ReferenceError: b is not defined
aaa()();
闭包的作用
闭包的作用是保存和保护。
保存作用
当我们在网页中使用选项卡时,通常会遇见因为索引值引发的问题。
<ul>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
<li>我是li</li>
</ul>
var lis = document.getElementsByTagName('li');
// 此方法不可行
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
console.log(i); //5 5 5
}
}
此时的运行结果打印的都是lis.length的值,即5。不管你点击哪一个li,打印的都是5.
解决方案:
当点击事件执行时,就会在私有作用域查找i的值,此时私有作用域中没有i,就会全局作用域查找,而此时全局作用域的值已经改变,所以,需要创建一个私有作用域的i。
// 解决方案一 闭包的形式
for (var i = 0; i < lis.length; i++) {
function getli(i) {
lis[i].onclick = function () {
console.log(i);
}
}
getli(i)
}
// 解决方案二 使用自定义属性
for (var i = 0; i < lis.length; i++) {
lis[i].index = i;
lis[i].onclick = function () {
console.log(this.index); //0 1 2 3 4
// console.log( lis[i].index);
}
}
// 解决方案三 使用let声明变量
// let 是块级作用域
for (let i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
lis[i].style.color="red"
console.log(i); //0 1 2 3 4
}
}
保护作用
在闭包内可以保护一些变量,闭包函数是一个私有作用域,当程序猿/媛在开发时,为了避免相互之间的变量名冲突,可以将其放在一个私有作用域下。