Ant Design Pro中Transfer穿梭框的实际用法(与后端交互)

Stella981
• 阅读 925

Ant Design Pro中Transfer穿梭框的实际用法(与后端交互)


该控件的属性以及属性的作用在ADP的官方文档中都有介绍,但没有讲如何与后端交互,本文旨在讲解该控件与后端的交互。 Ant Design官方文档


先来看需求是怎样的,以及实现的效果

Ant Design Pro中Transfer穿梭框的实际用法(与后端交互)

需求:管理某个场馆中的活动,可以对这个场馆进行加入活动和移出活动。 如图,初始进入到这个页面后,韵苑体育馆中有两个活动:活动1、活动5,其余活动在右边的框中(不属于该场馆)。选中右边框中的活动,可以进行移入操作。选中左边的活动,可以进行移出活动。

第一步:从后端取数据

(1)首先,我在该model(namesapce为themeList)的state中定义了两个数据

    activitys: {
      list: [],
    },
    emptyActivitys: {
      list: [],
    }

activitys是上图中属于左边框的活动,即场馆中的活动。emptyActivitys是上图中右边框的活动,即不属于该场馆中的活动。这两个集合没有交集。

(2)接下来就是该页面在加载的时候从后端取数据并放到这两个属性中,这里需要熟悉Ant Design Pro框架的用法以及React交互原理,就不再这里进行赘述了。

第二步:引进该控件

方便起见,我在使用这个控件时没有做代码规范,直接在该页面的代码上添加了该控件代码。

@connect(({ themeList, loading }) => ({
  themeList,
  submitting: loading.effects['themeList/'],
}))
class App extends React.Component {
  handleChange = targetKeys => {
    const {
      themeList: { emptyActivitys },
    } = this.props;    //从model中取出emptyActivitys
    const { dispatch, themeList } = this.props;

    var addList = []; // 需要添加到当前场馆的活动
    var removeList = []; // 需要移出当前场馆的活动

    //每次点击按钮,都会判断是否有移出的活动或者移入的活动
    
    // 移出
    for (var i = 0; i < targetKeys.length; i++) { 
      var key = targetKeys[i];
      var has = false;
      for (var j = 0; j < emptyActivitys.list.length; j++) {
        if (emptyActivitys.list[j].key == key) {
          has = true;
          break;
        }
      }
      if (has) continue;
      removeList.push(key);
    }
    //targetKeys是右框中活动的Key,不是选中的Key,是在点击“移入”后(即用户已经看到了活动移过去)才调用handleChange
    
    // 移入
    for (var i = 0; i < emptyActivitys.list.length; i++) {
      var key = emptyActivitys.list[i].key;
      var has = false; 
      for (var j = 0; j < targetKeys.length; j++) {
        if (targetKeys[j] == key) {
          has = true;
          break;
        }
      }
      if (has) continue;
      addList.push(key);
    }

    //再利用两个for循环,实现接口调用
    for (var i = 0; i < addList.length; i++) {
      dispatch({
        type: 'themeList/api_addActivityToTheme',
        payload: {
          themeId: themeList.detailId,
          activityId: addList[i],
        },
      });
    }

    for (var i = 0; i < removeList.length; i++) {
      dispatch({
        type: 'themeList/api_deleteActivityFromTheme',
        payload: {
          themeId: themeList.detailId,
          activityId: removeList[i],
        },
      });
    }
  };

  render() {
    const {
      themeList,
      themeList: { activitys, emptyActivitys },
    } = this.props;
    var list = [];
    var keys = [];

    for (var i = 0; i < activitys.list.length; i++) {
      // 把场馆中的活动的id赋值给key属性
      activitys.list[i].key = activitys.list[i].activityId;
      // 把场馆中的活动加入到集合list中
      list.push(activitys.list[i]);
    }

    for (var i = 0; i < emptyActivitys.list.length; i++) {
      emptyActivitys.list[i].key = emptyActivitys.list[i].activityId;
      list.push(emptyActivitys.list[i]);
      keys.push(emptyActivitys.list[i].key);
    } //keys保留着不属于当前场馆的活动ID

    return (
      <Transfer
        dataSource={list}
        showSearch
        listStyle={{
          width: 250,
          height: 300,
        }}
        operations={['移出', '移入']}
        targetKeys={keys} //targetKeys是页面右边的框:即不属于当前场馆的活动
        onChange={this.handleChange}
        titles={[themeList.detailName, '所有活动']}
        render={item => `${item.title}-${item.label}`}
      />
    );
  }
}

1、@connect不用介绍,用于将该控件与指定的medel绑定。 2、该控件中只含有一个方法:handleChange 3、在transer控件的属性中,targetKeys指的是右边框中的集合的Keys,所以我首先自定义了一个空的keys,然后把empyActivitys的key放到keys中。dataSource指的是所有的集合,即左边和右边的合集。所以在render中会有两个for循环,一个是将所有活动放在list中,另一个是将非场馆活动放在keys中。 4、选中活动,点击按钮,会触发handleChange函数(点击按钮才触发,不是选中活动)。在该函数中,我定义了addList和removeList,用于指定哪些活动被添加或者被移除。 5、用两个for循环,对addList和removeList进行填充。 6、再用两个for循环,对addList和removeList中的每个元素进行相应接口的调用。

第三步:修改当前的activitys和emptyActivitys

在完成上述的加入和移出活动后,此时的activitys和emptyActivitys应该被改变,但在实际的model中他们是不会变的,所以只能自己手动的进行更改。

先看看model中的effects的方法:

      *api_deleteActivityFromTheme({ payload }, { call, put }) {
      var activityId = payload.activityId;
      const response = yield call(api_deleteActivityFromTheme, payload);
      if (isResponseSuccess(response)) {
        // success
        yield put({
          type: 'save_deleteActivityFromStadium',
          payload: activityId,
        });
      } else {
      }
    },
    *api_addActivityToTheme({ payload }, { call, put }) {
      var activityId = payload.activityId;
      const response = yield call(api_addActivityToTheme, payload);
      if (isResponseSuccess(response)) {
        // success
        yield put({
          type: 'save_api_addActivityToStadium',
          payload: activityId,
        });
      } else {
      }
    },

上述代码正是那最后两个for循环调用的接口

然后该改变是在model中的reducer中进行改变的:

    save_api_addActivityToStadium(state, action) {
      var l = null;
      var list = [];
      for (var i = 0; i < state.emptyActivitys.list.length; i++) {
        if (state.emptyActivitys.list[i].activityId == action.payload) {
          l = state.emptyActivitys.list[i];
        } else {
          list.push(state.emptyActivitys.list[i]);
        }
      }
      state.emptyActivitys.list = list;
      state.activitys.list.push(l);
      return {
        ...state,
      };
    },
        save_deleteActivityFromStadium(state, action) {
      var l = null;
      var list = [];
      for (var i = 0; i < state.activitys.list.length; i++) {
        if (state.activitys.list[i].activityId == action.payload) {
          l = state.activitys.list[i];
        } else {
          list.push(state.activitys.list[i]);
        }
      }
      state.activitys.list = list;
      state.emptyActivitys.list.push(l);
      return {
        ...state,
      };
    },

简单来说,就是在加入和移出后,我要更新activitys和emptyActivitys这两个数据,否则会造成逻辑的错误。

注意:该控件的限制在于需要后端提供相应的接口,且算法不简单,但由于产品经理的硬性要求,不得已这么写了,有许多不规范的地方还请大佬们指教。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
2年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
2年前
SpringMvc接受特殊符号参数被转义
WEB开发时,在前端通过get/post方法传递参数的时候 如果实参附带特殊符号,后端接收到的值中特殊符号就会被转义例如该请求: http://localhost:10001/demo/index.do?name张三(1)注:中文()不会出现此种情况后台就收到的实际name值为:  张三&40;1&41;&40;其实为h
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这