积累
成年人的成长在于一次次的积累
# E01
# 写 React / Vue 项目时为什么要在列表组件中写 key,其作用是什么?
第一次看到这道题应该是刚接触vue和react的时候,当时肯定会不假思索的回答到是为了提高diff效率,在列表组建发生变化时能更好的得到响应。 而实际上呢?在简单列表渲染过程中,没有绑定key的反而速度更快。的确是这样的,在简单模板且没有绑定key的情况下,会导致虚拟新旧节点对比更快,节点也会
原地复用,关于简单模板且没有绑定key请看,但是这个并不是key的作用,所以片面的说绑定key能提高diff效率是不严谨的。 那么key的作用是什么呢? 我的简单理解是为了在diff中,针对可变表单(或是相同的节点组)的同级比较效率。z在更新组件时判断两个节点是否相同。相同就复用,不相同就删除旧的创建新的。
# 更准确
因为当虚拟节点带上了key值,就不会存在原地复用的情况,不会出现对比错位
# 更快
利用key的唯一性生成map对象来获取对应节点,比遍历方式更快。
这里需要额外补充diff算法的基本知识。
# ['1', '2', '3'].map(parseInt) what & why ?
答案是[1,2,3],完事了。
但是去控制台试了一下,瞬间怀疑人生。
答案是[1,NaN,NaN]
我们先确定map()的用法,map是js数组对象上的一个方法,语法为:
array.map(function(value,index,arr),thisValue)
map接受两个参数,第一个参数是必有的,一个函数,数组中的每一个元素都会执行这个函数,该函数的参数有三个value是必须的,其余两个是可选;
map的第二个参数是可选的,改变this指向。
map是有返回值的,返回的是一个新数组。该新数组是愿数组经过function后的。
接着我们看parseInt()方法,该方法解析一个字符串,并返回一个整数。
paeseInt(string,radix)
string:必需,要被解析的字符串。
radix:可选,表示要解析的数字的基数,该值的范围是 2~36.如果小于2或大于36,返回NaN,如果缺失或者为0,那么以10来解析,如果“0x”“0X”,将以16为基数。
返回值是解析后的数字
最后我们来看题干
['1', '2', '3'].map(parseInt)就等于
['1', '2', '3'].map(parseInt(value,index))
parseInt('1',0) 把字符串'1',以10为基数解析 ---- 1
parseint('2',1) radix=1<2 ----NaN
parseint('3',2) 3不是二进制 ----NaN
# 节流和防抖是什么?怎么实现?
节流,顾名思义节约流量,节流是连续触发事件的过程中以一定时间间隔执行函数。节流会稀释你的执行频率,比如每间隔1秒钟,只会执行一次函数,无论这1秒钟内触发了多少次事件。
function throttle(fn,time) {
let timeout; //声明定时器并且当一个标记使用
return function() { // 闭包
let that = this; // 记录必包this指向
if(!timeout){ //当没有定时器时,进入函数
timeout = setTimerout(function(){
timeout = null; //
fn.apply(that)
},time)
}
}
}
防抖,连续触发事件过程中不执行,事件触发后一定事件内只执行一次,如果在该时间内事件再次触发,则从头计时。
funcrion debounce(fn,time) {
let timeout;
return function() {
let that = this;
clearTimer(timeout);
timeout = setTimeout(function() {
fn.apply(that)
},time)
}
}
两者的区别就是节流没有关闭定时器,在第一次等待执行事件中(time时间内),即第一次开启定时器后 (!timeout) 为fasle,事件不会真正执行,只有等到第一个定时器工作时timeout=null后的事件才执行; 而防抖是只要都事件触发都会开启并关闭定时器,只有在一定时间内没有事件触发才会真正执行。