求教react树组件优化

#1

项目中需要用到树,用antd的tree组件有严重的性能问题,树结构同级5000个节点以上就很卡很卡了,需要优化,准备自己写个树,但是for循环一定要的啊,不知道有什么好的优化思路?

#2

antd tree 只是个组件而已,
所谓 MVC ,多数情况下 组件只运用在View层, 推荐你考虑在 Controller 中进行优化, 比如将5000个数据切分, 异步的传递给组件, 这样也好过重新实现一个Tree。

#3

谢谢,我现在用requestAnimationFrame来做了,用的就是异步的思路;不过,确实要自己写,因为每次选中antd的tree,都会很卡,选中与不选中,展开不展开之类的,还是有点麻烦;我自己就需要实现一两个tree的API,选中和展开的,改动相对来说还是少的

#4

在吗 楼主有点技术方面的问题想跟您请教下

#5

requestAnimationFrame分批次更新状态,自己控制shouldComponentUpdate解决部分问题,不过上w的数量级,还是卡,暂时没有好的办法。不过react16的时间分片据说很吊,可以中断渲染,项目暂时没升,你可以试试

#6

遇到同样的问题,几千个数据,用tree超级卡,选中的时候UI延迟上千毫秒。

#7

先放一个demo,数据是动态生成的10000个左右节点。
https://sheinsight.github.io/shineout/1.2.x/#/components/Tree

一般来说,上千数据的Tree并不会处于全部展开状态,要避免一次渲染节点过多。Shineout 的Tree节点是这样处理的

// 状态为未展开并且从未展开过的节点,不渲染
if (!expanded && !this.hasExpanded) return null
// 标记为展开过
this.hasExpanded = true

// 展开过的节点,通过 css 控制显示或隐藏
const newStyle = Object.assign({}, style, { display: expanded ? 'block' : 'none' })

精确控制组件粒度,把每次更新控制在最小范围。仔细考虑 Component 和 PureComponent 使用的时机。
带选择的Tree,如果把数据直接传下去,会导致整个 Tree 渲染。Shineout内部采用了一个辅助类 Datum.Tree 处理拦截了选中的value,向下传递这个对象,从而阻止节点渲染。节点上的Checkbox组件在初始化的时候注册到这个对象上,当value变化时,对象通知指定的Checkbox更新。

class Checkbox extends PureComponent {
  constructor(props) {
    super(props)
    this.handleChange = this.handleChange.bind(this)
    props.datum.bind(props.id, this.forceUpdate.bind(this))
  }

  componentWillUnmount() {
    this.props.datum.unbind(this.props.id)
  }

  handleChange(v, checked) {
    const { datum, id, onChange } = this.props
    datum.set(id, checked ? 1 : 0)
    onChange(datum.getValue())
  }

  render() {
    const { datum, id } = this.props
    const checked = datum.getChecked(id)

    return (
      <Checkbox
        checked={checked}
        onChange={this.handleChange}
      />
    )
}
2 Likes
#8

666,有启发意义

#9

你好,请问一下你那个优化的怎么样!我这边有个需求是支撑5w+的节点,选中和展开特别慢!

#10

请问具体思路是什么呢

#11

我是直接用requestAnimationFrame,没有在shouldComponentUpdate做任何逻辑,感觉是快很多,没那么卡顿了,不过你说的分批次更新具体思路是怎样的呢

#12

使用虚拟滚动,以列表的形式,自己构建树