使用react做管理后台项目遇到的问题和难点

使用react做管理后台项目, 一点点感悟与问题
1.全选翻页问题
场景描述: 对一个table列表数据进行操作, 将选中的数据加到另一个列表中, 并可以对源列表进行全选和查询操作.
问题描述:当使用全选功能, 对数据进行翻页, 会导致原来选中的数据被清空, 原因是antd的全选按钮, 只选择到了当前页的数据, 当切换之后又是另一页数据了.
解决方案一: 将列表数据变成二维数组, 实现多页操作, 并将数据扁平化之后加到需要添加进去的列表中, 关键代码如下:

使用react做管理后台项目遇到的问题和难点_第1张图片
说明: 在state中有以下值:
propsParameter.selectedRowKeys , //存放被选中项列表(二维数组)
propsParameter.onItem, // 扁平化后的列表数据, 用于在后一个列表展示数据
list:[], 源数据列表
在后一个列表删除数据的关键代码如下:
使用react做管理后台项目遇到的问题和难点_第2张图片
基本实现需求, 但仍然存在问题, 查询之后会删除被选择的值, 原因是翻页问题导致.查询时当前一般只有一页,选中之后按页码来增删数据,当前查询数据会覆盖原来的第一页数据.
解决方案二: 穿梭框方案
使用react做管理后台项目遇到的问题和难点_第3张图片
使用react做管理后台项目遇到的问题和难点_第4张图片

总结: 使用穿梭框基本上就实现了业务需求, 但由于没有分页功能, 数据加载可能会相对有影响,如果之后有更好的方式,再补上.

  1. 路由跳转问题
    在菜单内部实现跳转时,会出现数据未加载问题.原因是内部切换菜单时没有触发model层的入口函数, 导致触发请求来获取数据.
    解决方案: 写一个有生命周期的子组件, 通过子组件的componentDidMount来触发父组件, 从而触发请求数据的接口. 因为子组件的componentDidMount函数会在每一次进入时触发.
    总结: 这个解决方式有些投机取巧, 借助有生命周期的子组件来实现接口请求触发,不是一个很明智的选择.

  2. 名称过长导致的样式问题
    解决方式: word-break:break-all; white-space:normal

  3. 调用浏览器的打印问题
    调用浏览器的打印: window.print(),
    设置打印样式: @media print{}

5.关于树形结构的问题
场景需求: 在选择战区省份城市时,需要动态加载城市下的经销商数据, 并且编辑时需要回显被选中的经销商。
解决方案: antd的tree树形选择组件
具体实现方式请查看这篇文章 antd的tree树形组件异步加载数据小案例

6.关于前端数据处理问题
场景需求:点击新增按钮之后新增一个问题, 其中包含题目、类型和选项等,需要对问题进行删减,对选项进行删减上下移动操作,并且选项中可以包含图片。
view.jsx
//页面方法

    //状态值变化
  function updateModel(value, name, modHierarchy) {
    if(name==='attendType'){
      updateModel(0, 'attendBenefit', 'attendInfo')
    }
    let obj = modelObj;
    if (modHierarchy) {
      modHierarchy = modHierarchy.split(".");
      if(modHierarchy&&modHierarchy.length > 0){
        modHierarchy.map(e => {
          obj = obj[e];
        });
      }
    }
    obj[name] = value;

    // 分发到model
    dispatch({
      type: `${namespace}/updateModel`,
      payload: obj
    });
  };
 //更换questions问题集合专用方法
  const changeQuestion = (value, ind, wrapLabel, label, deepLabel)=> {
    let ques = cloneDeep(modelObj[wrapLabel]);
    ques.map((item,index)=> {
      if(index === ind){
        item[label] = value;
        if(value == 3 && label == 'questionType'){
          item.options.length = 1;
        }
      }  
    })
    updateModel(ques, wrapLabel);
  }
  // 修改指定问题的选项
  const changeOptions = (value, quIndex, opIndex, label) => {
    let ques = cloneDeep(modelObj['questions']);
    
    ques[quIndex].options[opIndex][label] = value;

    updateModel(ques, 'questions');

  }
  //问卷中的图片上传处理
  const changeOptionImg =(info, quIndex, opIndex, label) => {
    let fileUrl = '';
    if (info.file.status === 'done') {
      message.success('上传成功');
      fileUrl = info.file.response.data;
    }
    changeOptions(fileUrl, quIndex,opIndex, label);
  }
  //添加问题
  const addQuestion = () => {
    dispatch({
      type: `${namespace}/addQuestion`,
      payload: {
      }
    });
  }

  //删除问题
  const removeQuestion = (index) => {
    dispatch({
      type: `${namespace}/removeQuestion`,
      payload: {
        index
      }
    });
  }
  //添加奖项
  const addPrizes = () => {
    dispatch({
      type: `${namespace}/addPrizes`,
      payload: {
      }
    });
  }
 //删除奖项
  const removePrizes = (index) => {
    if(modelObj.prizes.length>2){
      dispatch({
        type: `${namespace}/removePrizes`,
        payload:{
          index
        }
      });
    }else{
      message.error('奖项配置不能少于两个!')
    }
  }

//页面渲染

 
              {
                modelObj.questions && modelObj.questions.map((item,index) => {
                    return (
                       removeQuestion(index)} type="close-circle" theme="filled" style={{fontSize:'20px',color:'#fff',cursor:'pointer'}}/>}
                       title={`问题${index+1}`} key={"Index_" + index}>
                         changeQuestion(e.target.value, index, 'questions', 'questionType')}>
                          单选
                          多选
                          填空
                        
                        
changeQuestion(e.target.value, index, 'questions','questionTitle')}/>
{let num = checked ? 1:0; changeQuestion(num, index, 'questions','required')} }/> {item.questionType===2 &&
changeQuestion(value, index,'questions','choiceMinNum')}/>
changeQuestion(value,index, 'questions','choiceMaxNum')}/>
}
{ item.options.map((tem,dex) => { return (
{ item.questionType!==3 &&
changeOptions(e.target.value, index, dex, 'optionTitle')}/> beforeUpload(file,2)} onChange={(info)=>changeOptionImg(info,index, dex,'imageUrl')} > { tem.imageUrl? :
上传
}
addOptions(index, item.options.length)}/> deleteOptions(index,dex,tem)}/> upOptions(index,dex)} /> downOptions(index,dex)} />

说明:图片建议尺寸:220x170px, 大小小于200kb, 仅支持jpg、png格式

} { item.questionType === 3 &&
changeOptions(value, index, dex, 'leastLength')}/>
changeOptions(value, index, dex, 'maxLength')}/>
}
) }) } { item.questionType!==3 &&
}
) }) }

//mod.js(model层)

//添加问题
    *addQuestion({ payload }, { put, call, select }) {
      let { questions } = yield select(e => e[tmpModule.namespace]);
      console.log('questions-->',questions.length+1);
      let tempObj = {
        questionSeq:questions.length+1, //问题排序
				questionType: 1, //问题类型:1.单选题,2.多选题.3.填空题
				questionTitle: "", //问题标题
				required: 0, //问题必填:0非必填,1必填
				choiceMinNum: '', //最少选择数量
        choiceMaxNum: '', //最多选择数量
				options: [//选项集合
					{
						optionTitle: "", //选项标题
            imageUrl: "",//图片
            optionSep:1,//排序
						localTitle:"选项1",//选项描述
						inputTips: "",//输入提示
						leastLength: '',//最少字数
						maxLength: '',//最多字数
					}
				]
			}
      questions.push(tempObj);
      yield put({type: 'store',payload: {questions} });  
    },
  //删除问题
    *removeQuestion({ payload }, { put, call, select }) {
      let { questions } = yield select(e => e[tmpModule.namespace]);
      questions.splice(payload.index,1);
      yield put({type: 'store',payload: {questions} });
    },
  //添加问卷中的选项
    *addOption({payload}, {put,call, select}) {
      let { questions, optionId} = yield select(e => e[tmpModule.namespace]);

      let {options} = questions[payload.index];
      console.log('options=--->', options);
      optionId++;

      payload.obj.optionId = optionId;

      // console.log('OptionId-->', optionId)
      
      options.push(payload.obj)
      yield put({
        type: 'store',
        payload: {
          questions,
          optionId
        }
      });     
    },
   //删除问卷中的选项
    *deleteOptions({payload}, {put,call, select}) {
      let { questions, optionId} = yield select(e => e[tmpModule.namespace]);
      let {queIndex,OpIndex,optionsItem} = payload;

      questions.filter((item,index)=>{
        if(index+''===queIndex+''){
          //return item.options[OpIndex].optionSep === optionsItem.optionSep
          if(item.options.length===1){
            return message.error('至少保留一个选项!');
          }else{
            return item.options.splice(OpIndex,1);
          }
        }
      })
      
      yield put({
        type: 'store',
        payload: {
          questions
        }
      });     
    },
    //上移问卷中的选项
    *upOptions({payload}, {put,call, select}) {
      let { questions} = yield select(e => e[tmpModule.namespace]);
      let {queIndex,OpIndex} = payload;

      questions.filter((item,index)=>{
        if(index+''===queIndex+''){
          item.options[OpIndex-1].optionSep = OpIndex+1;
          item.options[OpIndex].optionSep = OpIndex;

          let tmp = item.options[OpIndex];
          item.options[OpIndex] = item.options[OpIndex-1];
          item.options[OpIndex-1] = tmp;
          //return item.options.splice(OpIndex,1);
        }
      })

      yield put({
        type: 'store',
        payload: {
          questions
        }
      });  
    },
  //下移问卷中的选项
    *downOptions({payload}, {put,call, select}) {
      let { questions} = yield select(e => e[tmpModule.namespace]);
      let {queIndex,OpIndex} = payload;
      
      questions.filter((item,index)=>{
        if(index+''===queIndex+''){
          item.options[OpIndex].optionSep = OpIndex+2;
          item.options[OpIndex+1].optionSep = OpIndex+1;

          let tmp = item.options[OpIndex];
          item.options[OpIndex] = item.options[OpIndex+1];
          item.options[OpIndex+1] = tmp;
          //return item.options.splice(OpIndex,1);
        }
      })

      yield put({
        type: 'store',
        payload: {
          questions
        }
      });  
    },
    //新增奖项
    *addPrizes({ payload }, { put, call, select }) {
      let { prizes } = yield select(e => e[tmpModule.namespace]);
      let tempObj = {
        prizeId: "1", //奖品id
				prizeType: 2, //奖项类型:1.积分,2.礼品.3.抽奖次数,4谢谢参与
				prizeName: '', //奖品名称(赠送积分/礼品名称/赠送次数)
				prizeNumber: '', //奖品数量
				numerator: '',//中奖概率
				seq:1,//奖品排序
				prizeTips: '',//中奖提醒
				prizeImageUrl:'',//奖品图片
        prizeDelivery:1, //礼品发放方式:1验证码,2邮寄
        useBeginDatetime:'', //核销开始时间
        useEndDatetime:'', //核销结束时间
        attendIntegralName:'',//积分名称
        attendIntegralCode:'',//积分编码
			}
      prizes.push(tempObj);
      yield put({type: 'store',payload: {prizes} });     
    },
    //删除奖项
    *removePrizes({ payload }, { put, call, select }) {
      let { prizes } = yield select(e => e[tmpModule.namespace]);
      prizes.splice(payload.index,1);
      yield put({type: 'store',payload: {prizes} });
    },

你可能感兴趣的:(react从入门到放弃,antd)