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


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

Ant Design官方文档


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

需求:管理某个场馆中的活动,可以对这个场馆进行加入活动和移出活动。

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

第一步:从后端取数据

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

  1. activitys: {
  2. list: [],
  3. },
  4. emptyActivitys: {
  5. list: [],
  6. }

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

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

第二步:引进该控件

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

  1. @connect(({ themeList, loading }) => ({
  2. themeList,
  3. submitting: loading.effects['themeList/'],
  4. }))
  5. class App extends React.Component {
  6. handleChange = targetKeys => {
  7. const {
  8. themeList: { emptyActivitys },
  9. } = this.props; //从model中取出emptyActivitys
  10. const { dispatch, themeList } = this.props;
  11. var addList = []; // 需要添加到当前场馆的活动
  12. var removeList = []; // 需要移出当前场馆的活动
  13. //每次点击按钮,都会判断是否有移出的活动或者移入的活动
  14. // 移出
  15. for (var i = 0; i < targetKeys.length; i++) {
  16. var key = targetKeys[i];
  17. var has = false;
  18. for (var j = 0; j < emptyActivitys.list.length; j++) {
  19. if (emptyActivitys.list[j].key == key) {
  20. has = true;
  21. break;
  22. }
  23. }
  24. if (has) continue;
  25. removeList.push(key);
  26. }
  27. //targetKeys是右框中活动的Key,不是选中的Key,是在点击“移入”后(即用户已经看到了活动移过去)才调用handleChange
  28. // 移入
  29. for (var i = 0; i < emptyActivitys.list.length; i++) {
  30. var key = emptyActivitys.list[i].key;
  31. var has = false;
  32. for (var j = 0; j < targetKeys.length; j++) {
  33. if (targetKeys[j] == key) {
  34. has = true;
  35. break;
  36. }
  37. }
  38. if (has) continue;
  39. addList.push(key);
  40. }
  41. //再利用两个for循环,实现接口调用
  42. for (var i = 0; i < addList.length; i++) {
  43. dispatch({
  44. type: 'themeList/api_addActivityToTheme',
  45. payload: {
  46. themeId: themeList.detailId,
  47. activityId: addList[i],
  48. },
  49. });
  50. }
  51. for (var i = 0; i < removeList.length; i++) {
  52. dispatch({
  53. type: 'themeList/api_deleteActivityFromTheme',
  54. payload: {
  55. themeId: themeList.detailId,
  56. activityId: removeList[i],
  57. },
  58. });
  59. }
  60. };
  61. render() {
  62. const {
  63. themeList,
  64. themeList: { activitys, emptyActivitys },
  65. } = this.props;
  66. var list = [];
  67. var keys = [];
  68. for (var i = 0; i < activitys.list.length; i++) {
  69. // 把场馆中的活动的id赋值给key属性
  70. activitys.list[i].key = activitys.list[i].activityId;
  71. // 把场馆中的活动加入到集合list中
  72. list.push(activitys.list[i]);
  73. }
  74. for (var i = 0; i < emptyActivitys.list.length; i++) {
  75. emptyActivitys.list[i].key = emptyActivitys.list[i].activityId;
  76. list.push(emptyActivitys.list[i]);
  77. keys.push(emptyActivitys.list[i].key);
  78. } //keys保留着不属于当前场馆的活动ID
  79. return (
  80. <Transfer
  81. dataSource={list}
  82. showSearch
  83. listStyle={{
  84. width: 250,
  85. height: 300,
  86. }}
  87. operations={['移出', '移入']}
  88. targetKeys={keys} //targetKeys是页面右边的框:即不属于当前场馆的活动
  89. onChange={this.handleChange}
  90. titles={[themeList.detailName, '所有活动']}
  91. render={item => `${item.title}-${item.label}`}
  92. />
  93. );
  94. }
  95. }

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的方法:

  1. *api_deleteActivityFromTheme({ payload }, { call, put }) {
  2. var activityId = payload.activityId;
  3. const response = yield call(api_deleteActivityFromTheme, payload);
  4. if (isResponseSuccess(response)) {
  5. // success
  6. yield put({
  7. type: 'save_deleteActivityFromStadium',
  8. payload: activityId,
  9. });
  10. } else {
  11. }
  12. },
  13. *api_addActivityToTheme({ payload }, { call, put }) {
  14. var activityId = payload.activityId;
  15. const response = yield call(api_addActivityToTheme, payload);
  16. if (isResponseSuccess(response)) {
  17. // success
  18. yield put({
  19. type: 'save_api_addActivityToStadium',
  20. payload: activityId,
  21. });
  22. } else {
  23. }
  24. },

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

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

  1. save_api_addActivityToStadium(state, action) {
  2. var l = null;
  3. var list = [];
  4. for (var i = 0; i < state.emptyActivitys.list.length; i++) {
  5. if (state.emptyActivitys.list[i].activityId == action.payload) {
  6. l = state.emptyActivitys.list[i];
  7. } else {
  8. list.push(state.emptyActivitys.list[i]);
  9. }
  10. }
  11. state.emptyActivitys.list = list;
  12. state.activitys.list.push(l);
  13. return {
  14. ...state,
  15. };
  16. },
  17. save_deleteActivityFromStadium(state, action) {
  18. var l = null;
  19. var list = [];
  20. for (var i = 0; i < state.activitys.list.length; i++) {
  21. if (state.activitys.list[i].activityId == action.payload) {
  22. l = state.activitys.list[i];
  23. } else {
  24. list.push(state.activitys.list[i]);
  25. }
  26. }
  27. state.activitys.list = list;
  28. state.emptyActivitys.list.push(l);
  29. return {
  30. ...state,
  31. };
  32. },

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

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

Ant Design Pro中Transfer穿梭框的实际用法(与后端交互)的更多相关文章

  1. 实战 ant design pro 中的坑

    1.替换mock数据: 1.将:.roadhogrc.mock.js 中的代理模式替换 当不使用代理的时候就会将所有 /api/的链接换成 http://localhost:8080/ export ...

  2. 把antd的组件源码搬到Ant Design Pro中使用

    把组件源码搬过来后,样式死活不生效,经过1天的努力,有说less-loader的,有说webpack配置,还有说babel配置的,最后,我自己找到了方法 就是在global.less中使用@impor ...

  3. ant design pro (十五)advanced 使用 API 文档工具

    一.概述 原文地址:https://pro.ant.design/docs/api-doc-cn 在日常开发中,往往是前后端分离的,这个时候约定好一套接口标准,前后端各自独立开发,就不会被对方的技术难 ...

  4. ant design pro (十一)advanced Mock 和联调

    一.概述 原文地址:https://pro.ant.design/docs/mock-api-cn Mock 数据是前端开发过程中必不可少的一环,是分离前后端开发的关键链路.通过预先跟服务器端约定好的 ...

  5. ant design pro (八)构建和发布

    一.概述 原文地址:https://pro.ant.design/docs/deploy-cn 二.详细 2.1.构建 当项目开发完毕,只需要运行一行命令就可以打包你的应用: npm run buil ...

  6. ant design pro (七)和服务端进行交互

    一.概述 原文地址:https://pro.ant.design/docs/server-cn Ant Design Pro 是一套基于 React 技术栈的单页面应用,我们提供的是前端代码和本地模拟 ...

  7. ant design pro(二)布局

    一.概述 参看地址:https://pro.ant.design/docs/layout-cn 其实在上述地址ant-design上已经有详细介绍,本文知识简述概要. 页面整体布局是一个产品最外层的框 ...

  8. Ant Design Pro快速入门

    在上一篇文章中,我们介绍了如何构建一个Ant Design Pro的环境. 同时讲解了如何启动服务并查看前端页面功能. 在本文中,我们将简单讲解如何在Ant Design Pro框架下实现自己的业务功 ...

  9. Ant Design Pro 学习笔记:数据流向

    在讲这个问题之前,有一个问题应当讲一下: Ant Design Pro / umi / dva 是什么关系? 首先是 umi / dva 的关系. umi 是一个基于路由的 react 开发框架. d ...

随机推荐

  1. 前端知识体系(二)http请求

    https://blog.csdn.net/Lammonpeter/article/details/81358387 一.DNS解析 首先DNS域名系统的作用是将输入的url域名解析成ip地址以方便对 ...

  2. ipykernel_launcher.py: error: unrecognized arguments: -f /Users/apple/Library/Jupyter/runtime/kernel

    当在jupyter下使用parser.parse_args()出错则改换为parser.parse_known_args()[0]其效用是差不多的,至于为什么出现错误,我也不知道…

  3. css 文字超出部分隐藏

    未做隐藏处理 执行结果: 1.1行超出部分省略号 效果: 2.多行超出部分隐藏(目前只能在chrome浏览器中使用,其他浏览器不兼容) 效果: -webkit-line-clamp 属性定义显示行数可 ...

  4. 【CSS3】精美横向滚动菜单按钮

    废话不多说,直接上图: 然后是代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  5. 2003年NOIP普及组复赛题解

    题目涉及算法: 乒乓球:简单字符串模拟: 数字游戏:区间DP: 栈:卡特兰数 麦森数:高精度.快速幂.数学. 乒乓球 题目链接:https://www.luogu.org/problem/P1042 ...

  6. H3C 帧中继基本配置命令

  7. javascript修改css样式表

    //创建var sheet=document.createElement('style');document.bodt.appendChild(sheet);sheet.styleSheet.cssT ...

  8. 2018-11-13-WPF-禁用实时触摸

    title author date CreateTime categories WPF 禁用实时触摸 lindexi 2018-11-13 10:45:37 +0800 2018-5-4 21:0:3 ...

  9. MFC 封装类为静态链接库

    mfc自带的基本控件都不怎么美观,所以一般开发者都会自定义类对控件进行重绘.手里也积累了不少控件的重绘,对对话框.静态文本.列表框等. 但是每次都要把这些类重新导入到新的工程里,比较麻烦,而且我也不想 ...

  10. ABP运行Login failed for user 'IIS APPPOOL XXXXX Reason: Could not find a login matching the name provided问题解决

    我们在ABP官网上面生成解决方案后,编译完成,将数据库连接字符串中的Ip改成自己的测试数据库Ip直接在Vs里面调试运行没有任何问题. 发布之后到文件夹后运行,就报如下图异常. VS里面可以跑起来,单独 ...