在绑定 scroll 这类事件时,当它发生时,它被触发的频次非常高,间隔很近。如果事件中涉及到大量的位置计算、DOM 操作、元素重绘等工作且这些工作无法在下一个 scroll 事件触发前完成,就会造成浏览器掉帧。加之用户鼠标滚动往往是连续的,就会持续触发 scroll 事件导致掉帧扩大、浏览器 CPU 使用率增加、用户体验受到影响。
优化方法 1、防抖(debounce) 防抖技术可以把多个顺序地调用合并成一次,即在规定的时间间隔内只执行一次。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function debounce (func, wait, immediate ) {
var timeout;
return function ( ) {
clearTimeout(timeout);
timeout = setTimeout(func, wait);
};
};
function realFunc ( ) {
console .log("Success" );
}
window .addEventListener('scroll' ,debounce(realFunc,500 ));
window .addEventListener('scroll' ,realFunc);
2、节流(throttle) 节流技术只允许一个函数在 x 毫秒内执行一次,跟防抖技术主要的不同在于,保证 x 毫秒内至少执行一次。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
var timeout,
startTime = new Date ();
return function ( ) {
var context = this ,
args = arguments ,
curTime = new Date ();
clearTimeout(timeout);
if (curTime - startTime >= mustRun){
func.apply(context,args);
startTime = curTime;
}else {
timeout = setTimeout(func, wait);
}
};
};
function realFunc ( ) {
console .log("Success" );
}
window .addEventListener('scroll' ,throttle(realFunc,500 ,1000 ));
3、requestAnimationFrame实现节流方法 requestAnimationFrame 可替代 throttle,函数需要重新计算和渲染屏幕上的元素时,想保证动画或变化的平滑性,可以用它。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var ticking = false ;
function onScroll ( ) {
if (!ticking) {
requestAnimationFrame(realFunc);
ticking = true ;
}
}
function realFunc ( ) {
console .log("Success" );
ticking = false ;
}
window .addEventListener('scroll' , onScroll, false );
详见:高性能滚动 scroll 及页面渲染优化 实例解析防抖和节流函数 页面高性能滚动scroll优化——防抖与节流
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
function debounce (fn, wait ) {
var timmer
return function ( ) {
if (timmer) {
clearTimeout(timmer)
}
timmer = setTimeout(fn, wait)
}
}
function throttle (fn, delay ) {
let timer = null ;
return function ( ) {
if (timer) return false
timer = setTimeout(() => {
fn()
timer = null
}, delay)
}
}
function throttle (func, wait ) {
var args,
result,
thisArg,
timeoutId,
lastCalled = 0 ;
return function ( ) {
var now = new Date ,
remain = wait - (now - lastCalled);
args = arguments ;
thisArg = this ;
if (remain <= 0 ) {
lastCalled = now;
result = func.apply(thisArg, args);
}
else if (!timeoutId) {
timeoutId = setTimeout(() => {
lastCalled = new Date ;
timeoutId = null ;
result = func.apply(thisArg, args);
}, remain);
}
return result;
};
}
设置min-height的元素即使内容的高度很少时也能撑开到min-height设置的高度;当内容的高度大于min-height时就设置为内容的高度.
要使min-height的百分比值生效,其父元素的height 值必须为一个固定的高度 或者是一个有效的百分比高度 .
值得注意的是,父元素设置了有效的min-height但没有设置height属性时,子元素的height和min-height的百分比不会生效.因为设置height和min-height必须基于一个设置了固定高度或者是一个有效百分比高度的父元素.
vm.$on( event, callback ) 参数:
{String} event {Function} callback 用法:
监听当前实例上的自定义事件。事件可以由 vm.$emit, vm.$dispatch 或 vm.$broadcast触发。传入这些方法的附加参数都会传入这个方法的回调。
示例:
vm.$on(‘test’, function (msg) { console.log(msg) }) vm.$emit(‘test’, ‘hi’) // -> “hi”
vm.$emit( event, […args] ) 参数:
{String} event […args] 触发当前实例上的事件。附加参数都会传给监听器回调。
vm.$dispatch( event, […args] ) 参数:
{String} event […args] 用法:
派发事件,首先在实例上触发它,然后沿着父链向上冒泡在触发一个监听器后停止,除非它返回 true。附加参数都会传给监听器回调。
vm.$broadcast( event, […args] ) 参数:
{String} event […args] 用法:
广播事件,通知给当前实例的全部后代。因为后代有多个枝杈,事件将沿着各“路径”通知。每条路径上的通知在触发一个监听器后停止,除非它返回 true。
函数对象 由function创造出来的函数 系统内置函数对象 Function,Object,Number,String 只有函数对象才有 prototype 属性
原型对象 prototype 指针 proto 所有对象都有proto 属性,指向构造该对象的构造函数的prototype function Person() { this.name = ‘name’ } var person1 = new Person() person1._proto = Person.prototype
构造函数 constructor function Person() { this.name = ‘name’ } var person1 = new Person() person1.constructor = Person person1._proto.constructor = Person.prototype.constructor = Person
简单原型链继承 1
2
3
4
5
6
7
8
function Super ( ) {
this .name = 'super'
}
function Sub ( ) {
}
Sub.prototype = new Super()
构造函数继承 1
2
3
4
5
6
7
function Super ( ) {
this .name = 'super'
}
function Sub ( ) {
Super.call(this , ...arguments)
}
组合式继承 使用原型链实现对原型方法的继承,使用构造函数实现对实例属性的继承1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Super ( ) {
this .name = 'super'
}
Super.prototype.sayName = function ( ) {
return this .name
}
function Sub ( ) {
Super.call(this , ...arguments)
}
Sub.prototype = new Super()
Sub.prototype.constructor = Sub
Sub.prototype.sayAge = function ( ) {
return this .age
}
原型式继承 寄生式继承 1
2
3
4
5
6
7
function createAnother (original ) {
var clone = Object .create(original)
clone.sayHi = function ( ) {
console .log("Hi" )
}
return clone
}
组合寄生式继承 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Super ( ) {
this .name = 'super'
}
Super.prototype.sayName = function ( ) {
return this .name
}
function Sub ( ) {
Super.call(this , ...arguments)
}
Sub.prototype = Object .create(Super.prototype)
Sub.prototype.constructor = Sub
Sub.prototype.sayAge = function ( ) {
return this .age
}