积累

成年人的成长在于一次次的积累

# 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:可选,表示要解析的数字的基数,该值的范围是 236.如果小于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',23不是二进制   ----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后的事件才执行; 而防抖是只要都事件触发都会开启并关闭定时器,只有在一定时间内没有事件触发才会真正执行。

积累

成年人的成长在于一次次的积累

知乎日报Flutter版

使用Flutter框架、知乎日报openApi,仿写知乎日报APP。