在复杂页面中,某一个组件中的state发生变更,会导致页面重新调用render函数,可能会导致没有发生变更的组件被重复渲染,浪费性能。使用useMemo可以很好的解决这个问题。

  const RenderMenuArea = useMemo(() => {
    return (
      <>
        {menuConfig.num == 5 && usedConfig && usedConfig.map((item, index) =>
          5 * menuConfig.logo > index &&
          <div key={item.id} style={{ width: '20%', height: menuConfig.logo == 2 ? '50%' : '100%', display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center' }}>
            {item.exampleImage && <img src={item.exampleImage ?? ''} style={{ backgroundColor: '#fff', width: '30px', height: '30px', marginBottom: 8 }}>
            </img>}
            {!item.exampleImage && <div style={{ backgroundColor: '#fff', width: '30px', height: '30px', marginBottom: 8 }}>
            </div>}
            <div style={{ textAlign: 'center', color: '#666', fontSize: 12, height: 12 }}>
              {item.name ? item.name : ''}
            </div>
          </div>
        )}
        {menuConfig.num == 4 && usedConfig && usedConfig.map((item, index) =>
          4 * menuConfig.logo > index &&
          <div key={item.id} style={{ width: '25%', height: menuConfig.logo == 2 ? '50%' : '100%', display: 'flex', flexDirection: 'column', justifyContent: 'center', alignItems: 'center' }}>
            {item.exampleImage && <img src={item.exampleImage ?? ''} style={{ backgroundColor: '#fff', width: '30px', height: '30px', marginBottom: 8 }}>
            </img>}
            {!item.exampleImage && <div style={{ backgroundColor: '#fff', width: '30px', height: '30px', marginBottom: 8 }}>
            </div>}
            <div style={{ textAlign: 'center', color: '#666', fontSize: 12, height: 12 }}>
              {item.name ? item.name : ''}
            </div>
          </div>
        )}
      </>
    )
  }, [menuConfig, usedConfig, reflash])

通过 {RenderMenuArea} 在需要渲染的结构中展示,当依赖项中的某一个发生变更的时候,react会帮你监听到,并重新渲染这部分内容,在依赖项没有变更的时候,则不会重复渲染,可以提高页面渲染性能。

值得注意的是,众所周知,js中的数组和对象是引用类型的数据,他们的实质是类似于指针,记录的是一个内存地址,所以数组和对象中的值发生变化,并不会触发更新。这里可以采用给一个普通类型的变量比如reflash给一个数字型,然后需要变更页面时,手动给该值+1,来到达刷新页面的效果。

但是在此案例中,最后的排查发现,产生多次渲染的原因是循环渲染的key值没有给好。在vue或react框架中,循环渲染的key值是至关重要的,框架本身会根据key值是否变化,通过diff算法来决定是否刷新页面或者组件。所以给一个合适的key值可以减少刷新次数,提高渲染性能。最好是使用列表中的id spuCode这类唯一值。尽量不使用index作为key,因为插入或删除动作会导致其后的整个列表元素的index发生变化,存在性能浪费。更不能随便使用Math.random()这种东西,只要页面中的某个组件更新,就会导致所有的random重新获取,导致所有元素重新渲染,虽然页面感知不明显,但是本身是极大的浪费了渲染性能的。