Grids.jsx源码

/root/workspace/actionview/av-github-source-code/actionview-fe/app/components/gantt/Grids.jsx

actionview react前端Grids.jsx源码解读:这个组件负责根据传入的属性动态生成网格行,并根据折叠状态决定哪些行需要渲染详细信息,哪些行仅渲染空白占位符。_react.js

import React, { PropTypes, Component } from 'react';
import _ from 'lodash';

const $ = require('$');
const GridItem = require('./GridItem');
const GridEmptyItem = require('./GridEmptyItem');

export default class Grids extends Component {
  constructor(props) {
    super(props);
  }

  static propTypes = {
    cellWidth: PropTypes.number.isRequired,
    collection: PropTypes.array.isRequired,
    dates: PropTypes.object.isRequired,
    foldIssues: PropTypes.array.isRequired,
    markedIssue: PropTypes.object.isRequired,
    today: PropTypes.string.isRequired
  }

  render() {
    const { 
      cellWidth,
      collection, 
      dates, 
      foldIssues, 
      markedIssue, 
      today=''
    } = this.props;

    let offset = 0;
    let clientWidth = document.body.clientWidth;
    let scrollTop = 0;
    let clientHeight = document.body.clientHeight;
    if ($('div.ganttview-slide-container').length > 0) {
      offset = $('div.ganttview-slide-container').scrollLeft();
      clientWidth = $('div.ganttview-slide-container').get(0).clientWidth;
      scrollTop = $('div.ganttview-slide-container').scrollTop();
      clientHeight = $('div.ganttview-slide-container').get(0).clientHeight;
    }

    const dates2 = _.flatten(_.values(dates));
    const newCollection = _.reject(collection, (v) => v.parent && foldIssues.indexOf(v.parent.id) != -1);

    const topInd = _.max([ _.floor(scrollTop / 31) - 10, 0 ]);
    const bottomInd = _.min([ _.floor((scrollTop + clientHeight) / 31) + 10, newCollection.length - 1 ]);

    return (
      <div
        className='ganttview-grid'
        style={ { width: dates2.length * cellWidth + 'px' } }>
      { _.map(newCollection, (v, key) => {
        if (key < topInd || key > bottomInd) {
          return (
            <GridEmptyItem
              key={ v.id }
              cellWidth={ cellWidth }
              dates={ dates2 } />
            );
        } else {
          return (
            <GridItem
              key={ v.id }
              offset={ offset }
              clientWidth={ clientWidth }
              cellWidth={ cellWidth }
              dates={ dates2 }
              issue={ v }
              markedIssue={ markedIssue }
              today={ today } />
            );
        }
      } ) }
      </div>);
  }
}

源码解读

这段代码定义了一个名为 Grids 的 React 组件,用于渲染甘特图中的网格行。这个组件负责根据传入的属性动态生成网格行,并根据折叠状态决定哪些行需要渲染详细信息,哪些行仅渲染空白占位符。

代码分析

导入模块
import React, { PropTypes, Component } from 'react';
import _ from 'lodash';

const $ = require('$');
const GridItem = require('./GridItem');
const GridEmptyItem = require('./GridEmptyItem');
  • React:React 的核心库。
  • PropTypes:用于定义组件的 prop 类型检查。
  • lodash:一个实用工具库,提供了很多常用的函数,如 _.flatten_.reject
  • $:jQuery 库,用于 DOM 操作。
  • GridItem:一个子组件,用于渲染包含具体任务信息的网格行。
  • GridEmptyItem:一个子组件,用于渲染空白占位符的网格行。
定义组件类
export default class Grids extends Component {
  constructor(props) {
    super(props);
  }
  • Grids 类继承自 Component,表示这是一个 React 组件。
  • constructor 构造函数初始化组件,并调用父类构造函数 super(props) 来初始化父类属性。
定义 prop 类型
static propTypes = {
    cellWidth: PropTypes.number.isRequired,
    collection: PropTypes.array.isRequired,
    dates: PropTypes.object.isRequired,
    foldIssues: PropTypes.array.isRequired,
    markedIssue: PropTypes.object.isRequired,
    today: PropTypes.string.isRequired
  }
  • propTypes 是一个静态属性,用于定义组件接受的 prop 类型。
  • cellWidth:每个单元格的宽度。
  • collection:一个数组,包含所有任务信息。
  • dates:一个对象,其键为月份,值为该月每一天的信息。
  • foldIssues:一个数组,包含需要折叠的任务 ID。
  • markedIssue:一个对象,表示标记的任务。
  • today:今天的日期字符串。
渲染方法
render() {
    const { 
      cellWidth,
      collection, 
      dates, 
      foldIssues, 
      markedIssue, 
      today=''
    } = this.props;

    let offset = 0;
    let clientWidth = document.body.clientWidth;
    let scrollTop = 0;
    let clientHeight = document.body.clientHeight;
    if ($('div.ganttview-slide-container').length > 0) {
      offset = $('div.ganttview-slide-container').scrollLeft();
      clientWidth = $('div.ganttview-slide-container').get(0).clientWidth;
      scrollTop = $('div.ganttview-slide-container').scrollTop();
      clientHeight = $('div.ganttview-slide-container').get(0).clientHeight;
    }

    const dates2 = _.flatten(_.values(dates));
    const newCollection = _.reject(collection, (v) => v.parent && foldIssues.indexOf(v.parent.id) != -1);

    const topInd = _.max([ _.floor(scrollTop / 31) - 10, 0 ]);
    const bottomInd = _.min([ _.floor((scrollTop + clientHeight) / 31) + 10, newCollection.length - 1 ]);

    return (
      <div
        className='ganttview-grid'
        style={ { width: dates2.length * cellWidth + 'px' } }>
      { _.map(newCollection, (v, key) => {
        if (key < topInd || key > bottomInd) {
          return (
            <GridEmptyItem
              key={ v.id }
              cellWidth={ cellWidth }
              dates={ dates2 } />
            );
        } else {
          return (
            <GridItem
              key={ v.id }
              offset={ offset }
              clientWidth={ clientWidth }
              cellWidth={ cellWidth }
              dates={ dates2 }
              issue={ v }
              markedIssue={ markedIssue }
              today={ today } />
            );
        }
      } ) }
      </div>);
  }
}
  • render 方法返回组件的 JSX 结构。
  • 解构赋值 const { ... } = this.props 来提取传入的 props。
  • 获取当前滚动位置和可视区域尺寸:
  • offset:水平滚动偏移量。
  • clientWidth:可视区域的宽度。
  • scrollTop:垂直滚动位置。
  • clientHeight:可视区域的高度。
  • 如果存在 .ganttview-slide-container 元素,则从该元素获取滚动和尺寸信息。
  • 计算扁平化的日期数组 dates2
  • 计算过滤后的任务集合 newCollection,排除需要折叠的任务。
  • 计算顶部和底部索引 topIndbottomInd,用于确定哪些任务需要渲染。
  • 渲染一个 <div> 容器,作为网格的基础。
  • 使用 _.map 循环遍历 newCollection
  • 如果索引小于 topInd 或大于 bottomInd,则渲染 GridEmptyItem,表示该行仅需要空白占位符。
  • 否则,渲染 GridItem,表示该行需要详细信息。
  • 每个任务行都有唯一的 key 属性,以便 React 可以高效地管理 DOM 更新。

总结

这个 Grids 组件负责渲染甘特图中的网格行,根据传入的 props 动态生成网格行,并根据折叠状态决定哪些行需要渲染详细信息,哪些行仅渲染空白占位符。组件还考虑了滚动位置和可视区域尺寸,以优化渲染性能。

通过这种方式,组件能够灵活地适应不同的数据和布局需求,为用户提供清晰的任务进度视图,并且在滚动时只渲染可视区域的任务行,提高渲染效率。