主题
ReactDOM.createPortal
使用此方法可以修改挂载DOM的节点, 也可以通过事件冒泡到指定挂载的节点上

Modal, Tooltip, Popover, Popconfirm 的 getPopupContainer 是通过 ReactDOM.createPortal 方法对挂载节点的修改, 通常是因为这种是固定(fixed) 节点,挂载在 body 上,作为body的子元素, 但有时是需要自定义修改

RC-Component

  • overflow: 用于展示多个 Tag 或者文本

    常见问题

    穿梭框 Transfer

  • 使用搜索框时, 无论数据从 state 或者 props 传递, 在 filterOption 时 return false; onSearch 事件中不能使用异步加载事件, 尝试使用 setTimeout 模拟异步, 在 render 中 打印数据已经变动, 但子组件 Transfer 更新无效

  • 尝试使用 componentDidUpdate 对 prevState state 比较, 强制更新
  • 异步操作中 更新数据后 调用强制更新

测试DEMO 尝试解决方案如 问题

  • 同时使用 filterOption 和 onSearch , filterOption 不能 return false; 必须返回正确的判断规则
  • 单独使用 onSearch 异步加载完成之前会出现旧数据过滤
  • 貌似也没有使用 forceUpdate 也可以更新数据
  • 如果还不能正确展示数据时, 参考 45 行, 调用强制更新, 若在 dva 中, dispatch 后返回 promise, then 回调中调用 forceUpdate, 若使用的并非返回 promise, 在请求成功后添加回调方法中调用 forceUpdate
  • 官网未给定 demo展示, 初步判定本身组件并不支持异步加载
  • 官网少了一个API notFoundContent(自定义数据为空) 在 locale 中, 可直接使用
  • 需要添加loading
  • 缺少 API body 同 footer 使用一致

  1. import React from 'react';
  2. import { Transfer, Spin } from 'antd';
  3. import { isEqual, isNumber, throttle } from 'loadsh';
  4. let n = 0;
  5. class App extends React.Component {
  6. constructor() {
  7. super();
  8. this.state = {
  9. mockData: [],
  10. targetKeys: [],
  11. loading: false,
  12. }
  13. this.getMock = throttle(this.getMock, 1000);
  14. }
  15. componentDidMount() {
  16. this.getMock(5);
  17. }
  18. // componentDidUpdate(prevProps, prevState) {
  19. // if (!isEqual(prevState, this.state)) {
  20. // this.forceUpdate();
  21. // }
  22. // }
  23. getMock = (value) => {
  24. this.setState({ loading: true });
  25. const m = isNumber(value) ? value : 5;
  26. const targetKeys = [];
  27. const mockData = [];
  28. n += 1;
  29. for (let i = 0; i < m; i++) {
  30. const data = {
  31. key: `${i + n}${value}`,
  32. title: `content${i + n}${value}`,
  33. description: `description of content${i + n}`,
  34. chosen: Math.random() * 2 > 1,
  35. };
  36. // if (data.chosen) {
  37. // targetKeys.push(data.key);
  38. // }
  39. mockData.push(data);
  40. }
  41. setTimeout(() => {
  42. this.setState({ mockData, targetKeys, loading: false }, () => {
  43. // this.forceUpdate();
  44. });
  45. }, 1000);
  46. }
  47. // filterOption = (inputValue, option) => {
  48. // return option.key.indexOf(inputValue) > -1;
  49. // }
  50. // handleChange = (targetKeys) => {
  51. // this.setState({ targetKeys });
  52. // }
  53. handleSearch = (dir, value) => {
  54. if (dir === 'left') {
  55. this.getMock(value);
  56. }
  57. // console.log('search:', dir, value);
  58. };
  59. renderBody = (props) => {
  60. console.log(props, '>>>>>>');
  61. return (<div>body</div>);
  62. };
  63. render() {
  64. const { mockData, loading } = this.state;
  65. const notFoundContent = loading ? <Spin /> : '无数据';
  66. console.log(mockData, 'render>>>>>>>>>');
  67. return (
  68. <Transfer
  69. rowKey={record => record.key}
  70. dataSource={mockData}
  71. showSearch
  72. // filterOption={this.filterOption}
  73. targetKeys={this.state.targetKeys}
  74. onChange={this.handleChange}
  75. onSearch={this.handleSearch}
  76. render={item => item.title}
  77. notFoundContent={notFoundContent}
  78. // body={this.renderBody}
  79. />
  80. );
  81. }
  82. }
  83. ReactDOM.render(<App />, mountNode);