用react 构建电子表格(6)--父组件调用子组件

范围选择:先点击选择一个单元格,再按Ctrl键点击另外一个单元格,我们认为是范围选择动作。而且这2个动作必须是顺序且连续的。

 

点击的第一个单元格,记录在SelectCell1属性当中;

顺序?搞个属性,记录动作类型即可。

//table.js
//处理单元格选择   主要是改变相关样式数据
    handleCellSelect = (e,i,j) => {
         if(e.ctrlKey){     // 按下ctrl key  不用重新
            if(this.state.userActionType==1){  //上次动作点击的是单元格
             const current_table_model =this.state.history_record[this.state.history_record.length -1];
             this.state.selectCell2=new Array(i, j);  //当前选中的单元格坐标
             let row_start= this.state.selectCell1[0]<i ? this.state.selectCell1[0] :i;
             let row_end= this.state.selectCell1[0]>i ? this.state.selectCell1[0] :i;
             let col_start= this.state.selectCell1[1]<j ? this.state.selectCell1[1] :j;
             let col_end= this.state.selectCell1[1]>j ? this.state.selectCell1[1] :j;
             for(let  i=0;i<current_table_model.cell_addFilter_bright_model.length;i++){
                 for (let j=0;j<current_table_model.cell_addFilter_bright_model[i].length;j++){
                     current_table_model.cell_addFilter_bright_model[i][j]=0;  //范围内全部家filter
                 }
             }

             for (let i=row_start;i<=row_end;i++)
             {
                 for (let j=col_start;j<=col_end;j++){
                     current_table_model.cell_addFilter_bright_model[i][j]=1;  //范围内全部家filter
                 }
             }
             //setState 即可引发渲染
             this.setState({
                 history_record: this.state.history_record,
             });
            return;
            }
         }
        //复制一个history 元素,改变这个元素相关属性
        const history = this.state.history_record;
        const current =history.slice(history.length - 1)
        const table_model = current[0];
        //复制一个数组
        //let cellSelectStates_s=this.state.cellSelectStates;
        let cellSelectStates_s=table_model.cell_addFilter_bright_model ;
        let cellSelectStates_temp=[];
        // for(let i=0;i<cellSelectStates_s.length;i++){
        //     let [...cellSelectStates_r]=cellSelectStates_s[i];
        //     cellSelectStates_temp.push(cellSelectStates_r);
        // }
        for(let i=0;i<cellSelectStates_s.length;i++){
            cellSelectStates_temp.push(new Array(cellSelectStates_s[i].length).fill(0));
        }

        cellSelectStates_temp[i][j]=1;  //1表示选中
        table_model.cell_addFilter_bright_model=cellSelectStates_temp;
        this.state.selectCell1=new Array(i, j);  //当前选中的单元格坐标
        this.state.userActionType=1; //这个动作记录用户上次的操作


        this.setState({
            history_record: history.concat(table_model),
        });
    }

到这一步,我们就可以在表格上,选择范围了。效果如图:

追加行、追加列 插入行 插入列的实现:

先不考虑合并单元格带来的影响。

我甚至设想,最后一行,与最后一列,保留给系统专用,以它们作为坐标参考系。

在这个前提下,我们来实现追加动作。

追加行,就把当前表格最后一行数据复制一份,插入到数据的集合当中,当然,这些数据包括样式数据,目前好像有9、10项吧

table.js    
//追加行
    appendRow=()=>{
        //复制一个history 元素,改变这个元素相关属性
        const history = this.state.history_record;
        const current =history.slice(history.length - 1)
        const table_model = current[0];
        let newTable_model=this.appendRowInModel(table_model);
        this.setState({
            history_record: history.concat(newTable_model),
        });
    }

    appendRowInModel=(table_model)=>{
        let data_model=table_model.data_model ;  //是个2维数组
        //复制最后一行
        let lastRowData=data_model.slice(data_model.length - 1);
        var newRowData = [...lastRowData];
        //复制的数据加入到当前模型当中
        table_model.data_model=data_model.concat(newRowData)

        //2
        let cell_align_model=table_model.cell_align_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_align_model=cell_align_model.slice(cell_align_model.length - 1);
        var newRowlastRowcell_align_model = [...lastRowcell_align_model];
        //复制的数据加入到当前模型当中
        table_model.cell_align_model=cell_align_model.concat(newRowlastRowcell_align_model)
        //3
        let cell_border_top_model=table_model.cell_border_top_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_border_top_model=cell_border_top_model.slice(cell_border_top_model.length - 1);
        var newRowlastRowcell_border_top_model = [...lastRowcell_border_top_model];
        //复制的数据加入到当前模型当中
        table_model.cell_border_top_model=cell_border_top_model.concat(newRowlastRowcell_border_top_model)
        //4
        let cell_border_bootom_model=table_model.cell_border_bootom_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_border_bootom_model=cell_border_bootom_model.slice(cell_border_bootom_model.length - 1);
        var newRowcell_border_bootom_model = [...lastRowcell_border_bootom_model];
        //复制的数据加入到当前模型当中
        table_model.cell_border_bootom_model=cell_border_bootom_model.concat(newRowcell_border_bootom_model)
        //5
        let cell_border_left_model=table_model.cell_border_left_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_border_left_model=data_model.slice(cell_border_left_model.length - 1);
        var newRowcell_border_left_model = [...lastRowcell_border_left_model];
        //复制的数据加入到当前模型当中
        table_model.cell_border_left_model=cell_border_left_model.concat(newRowcell_border_left_model)
        //6
        let cell_border_right_model=table_model.cell_border_right_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_border_right_model=cell_border_right_model.slice(cell_border_right_model.length - 1);
        var newRowcell_border_right_model = [...lastRowcell_border_right_model];
        //复制的数据加入到当前模型当中
        table_model.cell_border_right_model=cell_border_right_model.concat(newRowcell_border_right_model)
        //7
        let cell_addFilter_bright_model=table_model.cell_addFilter_bright_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_addFilter_bright_model=cell_addFilter_bright_model.slice(cell_addFilter_bright_model.length - 1);
        var newRowcell_addFilter_bright_model = [...lastRowcell_addFilter_bright_model];
        //复制的数据加入到当前模型当中
        table_model.cell_addFilter_bright_model=cell_addFilter_bright_model.concat(newRowcell_addFilter_bright_model)
        //8
        let cell_cellBackgroundColor_model=table_model.cell_cellBackgroundColor_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_cellBackgroundColor_model=cell_cellBackgroundColor_model.slice(cell_cellBackgroundColor_model.length - 1);
        var newRowcell_cellBackgroundColor_model = [...lastRowcell_cellBackgroundColor_model];
        //复制的数据加入到当前模型当中
        table_model.cell_cellBackgroundColor_model=cell_cellBackgroundColor_model.concat(newRowcell_cellBackgroundColor_model)
        //9
        let cell_cell_font_css_model=table_model.cell_cell_font_css_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_cell_font_css_model=cell_cell_font_css_model.slice(cell_cell_font_css_model.length - 1);
        var newRowcell_cell_font_css_model = [...lastRowcell_cell_font_css_model];
        //复制的数据加入到当前模型当中
        table_model.cell_cell_font_css_model=cell_cell_font_css_model.concat(newRowcell_cell_font_css_model);
        return table_model;
    }

整个过程,没考虑优化、没考虑引用可能的影响,先这样吧。

追加行按钮在父组件当,点击按钮,需要调用子组件追加行的的方法。

父组件调用子组件过程分4步:

首先向下传递一个方法,这个方法的目的在于获取子组件的引用。子组件在生命周期方法 componentDidMount 中,会用这个函数传递自身的信息。这样,父组件就可以获取到子组件实例的的引用了.

以worksheet。js为例基本步骤如下:

1、定义workTableRef函数,把这个方法向子组件传递,以获取workTable的引用
2、把workTableRef函数传递给子组件

workshhet.js
  //1、定义workTableRef方法,把这个方法向子组件传递,以获取workTable的引用
  workTableRef=(ref)=>{
        this.workTable = ref   
    }
.....

2、传递给子组件
<CommTable  rowNum={rowNum} colNum={colNum}  onRef={this.workTableRef}/>;

3子组件在生命周期方法 componentDidMount 中,调用onRef方法,把自身传递给调用者。

//worktable.js 
   componentDidMount(){
        this.props.onRef(this)  //这个就是把自身传给调用者
    }

4、调用者调用子类的方法:

    workTableRef=(ref)=>{
        this.workTable = ref
    }

插入行的处理:取得当前行位置 即读取点击的位置,如果没有点击数据 有2种处理,1、啥都不干 2、追加到最后一行,我们先选择方式1进行处理。

插入行、删除行,必须确定当前选中的行。但为简化问题起见,我们只能一次删除一行 插入一行。需要的时候,我们再扩充相关功能。

插入、删除行的时候,额外要做2个处理:

1、清除选中行的记录 cell1、cell2; 如果不清除这个数据,再次点击删除的时候,还会删除一行,这是因为当前行数据记录还存在。

插入行的时候,系统记录的当前行是新插入的行,但被选择样式显示的在老行上,这种情况,有三种处理办法:

  • 清除选中信息
  • 选中信息移到新插入的行上
  • 选择信息向下移动一行

第一种方法,对我来说最简单吧,

2、最后一行原则上不能删除,因为我想把它留着当坐标。

   //insertRowType=-1 是追加行
   // insertRowType=-2 是插入行  当前位置从state当中取出
   //insertRowType=-3 是删除行
    appendRowInModel=(table_model,insertRowType)=>{
        //取得当前行位置 即读取点击的位置,如果没有点击数据  有2种处理,1、啥都不干 2、追加到最后一行
        let p1=-1;
        let p2=-1;
        if(this.state.selectCell1.length==2){
            p1=this.state.selectCell1[0];
        }
        if(this.state.selectCell2.length==2){
            p2=this.state.selectCell2[0];
        }
        //插入行 删除行 必须指定位置
        if(insertRowType==-2 || insertRowType==-3){
            if (p1==-1){
                alert("请选择一行再执行相关操作")
                return -1;}
            if(p2!=-1  && p1!=p2){
                alert("仅能选择一行再执行相关操作")
                return -1;
            }
        };


        let data_model=table_model.data_model ;  //是个2维数组
        let l=data_model.length - 1;
        if(p1==l  && insertRowType==-3){
            alert('最后一行不能删除');
            return -1;
        }

        //复制最后一行
        let lastRowData=data_model.slice(data_model.length - 1);
        let newRowData = [...lastRowData];
        //1、复制的数据加入到当前模型当中
        if(insertRowType==-1){
            table_model.data_model=data_model.concat(newRowData);
        }else if(insertRowType==-2){
            table_model.data_model.splice(p1,0,newRowData[0]);
            this.state.selectCell1=[];
            this.state.selectCell2=[];
            //全表清除选择样式
        }else if(insertRowType==-3){  //只删除一行
            table_model.data_model.splice(p1,1);
            this.state.selectCell1=[];
            this.state.selectCell2=[];
        }
        //2
        let cell_align_model=table_model.cell_align_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_align_model=cell_align_model.slice(cell_align_model.length - 1);
        var newRowlastRowcell_align_model = [...lastRowcell_align_model];
        //复制的数据加入到当前模型当中
        if(insertRowType==-1) {
            table_model.cell_align_model = cell_align_model.concat(newRowlastRowcell_align_model);
        }else  if(insertRowType==-2){
            cell_align_model.splice(p1,0,newRowlastRowcell_align_model[0]);
        }else if(insertRowType==-3){
            cell_align_model.splice(p1,1);
        }
            //3
        let cell_border_top_model=table_model.cell_border_top_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_border_top_model=cell_border_top_model.slice(cell_border_top_model.length - 1);
        var newRowlastRowcell_border_top_model = [...lastRowcell_border_top_model];
        //复制的数据加入到当前模型当中
        if(insertRowType==-1) {
            table_model.cell_border_top_model = cell_border_top_model.concat(newRowlastRowcell_border_top_model)
        }else if(insertRowType==-2){
            cell_border_top_model.splice(p1,0,newRowlastRowcell_border_top_model[0]);
        }else if(insertRowType==-3){
            cell_border_top_model.splice(p1,1);
        }
        //4
        let cell_border_bootom_model=table_model.cell_border_bootom_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_border_bootom_model=cell_border_bootom_model.slice(cell_border_bootom_model.length - 1);
        var newRowcell_border_bootom_model = [...lastRowcell_border_bootom_model];
        //复制的数据加入到当前模型当中
        if(insertRowType==-1) {
            table_model.cell_border_bootom_model=cell_border_bootom_model.concat(newRowcell_border_bootom_model);
        }else if(insertRowType==-2){
            cell_border_bootom_model.splice(p1,0,newRowcell_border_bootom_model[0]);
        }else if(insertRowType==-3){
            cell_border_bootom_model.splice(p1,1);
        }
            //5
        let cell_border_left_model=table_model.cell_border_left_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_border_left_model=data_model.slice(cell_border_left_model.length - 1);
        var newRowcell_border_left_model = [...lastRowcell_border_left_model];
        //复制的数据加入到当前模型当中
        if(insertRowType==-1) {
            table_model.cell_border_left_model=cell_border_left_model.concat(newRowcell_border_left_model);
        }else if(insertRowType==-2){
            cell_border_left_model.splice(p1,0,newRowcell_border_left_model[0]);
        }else if(insertRowType==-3){
            cell_border_left_model.splice(p1,1);
        }
            //6
        let cell_border_right_model=table_model.cell_border_right_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_border_right_model=cell_border_right_model.slice(cell_border_right_model.length - 1);
        var newRowcell_border_right_model = [...lastRowcell_border_right_model];
        //复制的数据加入到当前模型当中
        if(insertRowType==-1) {
            table_model.cell_border_right_model=cell_border_right_model.concat(newRowcell_border_right_model);
        }else if(insertRowType==-2){
            cell_border_right_model.splice(p1,0,newRowcell_border_right_model[0]);
        }else if(insertRowType==-3){
            cell_border_right_model.splice(p1,1);
        }
            //7
        let cell_addFilter_bright_model=table_model.cell_addFilter_bright_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_addFilter_bright_model=cell_addFilter_bright_model.slice(cell_addFilter_bright_model.length - 1);
        var newRowcell_addFilter_bright_model = [...lastRowcell_addFilter_bright_model];
        //复制的数据加入到当前模型当中
         if(insertRowType==-1) {
            table_model.cell_addFilter_bright_model=cell_addFilter_bright_model.concat(newRowcell_addFilter_bright_model);
         }else if(insertRowType==-2){
            cell_addFilter_bright_model.splice(p1,0,newRowcell_addFilter_bright_model[0]);
         }else if(insertRowType==-3){
             cell_addFilter_bright_model.splice(p1,1);
         }
             //8
        let cell_cellBackgroundColor_model=table_model.cell_cellBackgroundColor_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_cellBackgroundColor_model=cell_cellBackgroundColor_model.slice(cell_cellBackgroundColor_model.length - 1);
        var newRowcell_cellBackgroundColor_model = [...lastRowcell_cellBackgroundColor_model];
        //复制的数据加入到当前模型当中
        if(insertRowType==-1) {
             table_model.cell_cellBackgroundColor_model=cell_cellBackgroundColor_model.concat(newRowcell_cellBackgroundColor_model);
        }else if(insertRowType==-2){
            cell_cellBackgroundColor_model.splice(p1,0,newRowcell_cellBackgroundColor_model[0]);
        }else if(insertRowType==-3){
            cell_cellBackgroundColor_model.splice(p1,1);
        }
            //9
        let cell_cell_font_css_model=table_model.cell_cell_font_css_model ;  //是个2维数组
        //复制最后一行
        let lastRowcell_cell_font_css_model=cell_cell_font_css_model.slice(cell_cell_font_css_model.length - 1);
        var newRowcell_cell_font_css_model = [...lastRowcell_cell_font_css_model];
        //复制的数据加入到当前模型当中
        if(insertRowType==-1) {
            table_model.cell_cell_font_css_model=cell_cell_font_css_model.concat(newRowcell_cell_font_css_model);
        }else if(insertRowType==-2){
            cell_cell_font_css_model.splice(p1,0,newRowcell_cell_font_css_model[0]);
        }else if(insertRowType==-3){
            cell_cell_font_css_model.splice(p1,1);
        }
        if(insertRowType==-2 || insertRowType==-3){
            this.clearCssFilter(table_model);
        }
        return table_model;
    }

表格的坐标一直是心里的痛:

一个是搞个和具体表格无关的坐标;但这要搞实际表格和坐标间的转换

一个是全表动态计算坐标

一个是保留特殊的行、列作为坐标参考,例如首行首列,末行、末列。这个似乎最简单,搞首行首列、末行、末列作为保留行列吧,不能在首行首列末行、末列上,做任何操作。

也许用th作为参考更合理?

表格线的样式,我们大概总结了6-7种表格线,每种表格线需要设置一个单元格的4条边的样式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值