关于antd tree 和父子组件之间的传值问题(react 总结)


Posted in Javascript onJune 02, 2021

项目需求:点击产品树节点时获取该节点的所有父节点,同时回填表格的搜索条件,完成搜索功能,搜索结果展示在下方的table中。

关于antd tree 和父子组件之间的传值问题(react 总结)

写了三个组件:

关于antd tree 和父子组件之间的传值问题(react 总结)

现在有个业务场景交互:在orderTree组件中点击树节点,获取当前节点以及所有的父节点的Id 放入一个对象arrKeys中,并在orderForm组件中使用(回填类型下拉选择框,objId对象作为查询接口的入参)

现在可以分部解决问题:

1.首先获取点击的树节点以及所有父节点的id ---arrKeys

关于antd tree 和父子组件之间的传值问题(react 总结)

关于antd tree 和父子组件之间的传值问题(react 总结)

关于antd tree 和父子组件之间的传值问题(react 总结)

2.在点击树节点获取当前节点以及所有父级节点之后,通过this.props.idObject(arrKeys)把 arrKeys传给父组件。

关于antd tree 和父子组件之间的传值问题(react 总结)

3.在tree组件和form组件中的componentDidMount生命周期中把整个组件传给父组件

关于antd tree 和父子组件之间的传值问题(react 总结)

4.form组件中的inquery方法:

关于antd tree 和父子组件之间的传值问题(react 总结)

现附上tree.js代码

import React, { Component } from 'react';
import { connect } from 'dva';
import { Divider, Modal, Table, message, Tag, Spin } from 'antd';
import router from 'umi/router';
import style from '../style.less';
import { Tree, Input } from 'antd';

const { confirm } = Modal;
const { TreeNode } = Tree;
const { Search } = Input;
let dataList = [];
let keysObj = {}; // 当前节点以及所有父节点的id
let firstParentKey = {}; // 一级根节点的id
const intetorFun = (data, key, string) => {
  if (string) {
    firstParentKey = {
      [data.param]: data.paramId,
    };
  }
  if (data.children && data.children.length !== 0) {
    data.children.forEach(item => {
      if (item.id === key[0]) {
        keysObj = {
          [data.param]: data.paramId,
          [item.param]: item.paramId,
          ...firstParentKey,
        };
      } else {
        intetorFun(item, key);
      }
    });
  }
  return keysObj;
};
const getParentKey = (key, tree) => {
  let parentKey = [];
  for (let i = 0; i < tree.length; i++) {
    const node = tree[i];
    parentKey = intetorFun(node, key, 'firstTime');
  }
  return parentKey;
};
//搜索用的
const getSearchKey = (key, tree) => {
  let parentKey;
  for (let i = 0; i < tree.length; i++) {
    const node = tree[i];
    if (node.children) {
      if (node.children.some(item => item.id === key)) {
        parentKey = node.id;
      } else if (getSearchKey(key, node.children)) {
        parentKey = getSearchKey(key, node.children);
      }
    } else {
      if (node.id === key) {
        parentKey = node.id;
      }
    }
  }
  return parentKey;
};

@connect(({ commodity, loading, menu }) => ({
  commodity,
  loading: loading.effects['commodity/getTree'],
  menu,
}))
class OrderTree extends Component {
  constructor(props) {
    super(props);
    this.state = {
      expandedKeys: [], //默认展开一级根节点 props.commodity.defaultParentIdList
      searchValue: '',
      autoExpandParent: true,
    };
  }
  componentDidMount() {
    const { dispatch } = this.props;
    this.props.treeRef && this.props.treeRef(this); //挂载时把整个tree组件传给父组件
    dispatch({
      type: 'commodity/getTree',
      callback: res => {
        this.generateList(res.data);
        const defaultParentIdList = res.data.map(item => item.id);
        this.setState({
          expandedKeys: defaultParentIdList,
        });
      },
    });
  }
  generateList = data => {
    const { dispatch } = this.props;
    for (let i = 0; i < data.length; i++) {
      const node = data[i];
      const { id, name } = node;
      dataList.push({ id, name });
      dispatch({
        type: 'commodity/save',
        payload: {
          dataList,
        },
      });
      if (node.children) {
        this.generateList(node.children);
      }
    }
  };

  //展开/收起节点时触发
  onExpand = expandedKeys => {
    this.setState({
      expandedKeys,
      autoExpandParent: true,
    });
  };
  //点击树节点时触发
  onSelect = (selectKeys, e) => {
    const { dispatch } = this.props;
    const {
      commodity: { treeData },
    } = this.props;
    let arrKeys = {};
    //只有节点选中了才执行代码 dataRef是自定义在TreeNode上添加的属性,可以获取当前节点的所有信息
    if (e.selected && e.node.props.dataRef.param !== 'categoryId') {
      keysObj = {};
      firstParentKey = {};
      arrKeys = getParentKey(selectKeys, treeData);
    } else if (e.selected && e.node.props.dataRef.param === 'categoryId') {
      keysObj = {};
      firstParentKey = {};
      arrKeys = {
        categoryId: e.node.props.dataRef.paramId,
      };
    } else if (!e.selected) {
      return false;
    }
    this.props.idObject(arrKeys);
  };
  // 搜索功能
  onChange = e => {
    const { value } = e.target;
    const {
      commodity: { treeData, dataList, defaultParentIdList },
    } = this.props;
    let expandedKeys = [];
    if (value) {
      expandedKeys = dataList
        .map(item => {
          if (item.name.toLowerCase().indexOf(value.toLowerCase()) > -1) {
            //不区分大小写
            return getSearchKey(item.id, treeData);
          }
          return null;
        })
        .filter((item, i, self) => item && self.indexOf(item) === i);
      this.setState({
        expandedKeys,
        searchValue: value,
        autoExpandParent: true,
      });
    } else {
      this.setState({
        expandedKeys: defaultParentIdList,
        searchValue: '',
        autoExpandParent: true,
      });
    }
  };

  render() {
    const { searchValue, expandedKeys, autoExpandParent } = this.state;
    const {
      commodity: { treeData },
      loading,
    } = this.props;
    const loop = data =>
      data.map(item => {
        const index = item.name.toLowerCase().indexOf(searchValue.toLowerCase()); //忽略大小写
        const beforeStr = item.name.substr(0, index);
        const afterStr = item.name.substr(index + searchValue.length);
        const centerStr = item.name.substr(index, searchValue.length);
        const title =
          index > -1 ? (
            <span title={item.name}>
              {beforeStr}
              <span style={{ color: '#f50' }}>{centerStr}</span>
              {afterStr}
            </span>
          ) : (
            <span title={item.name}>{item.name}</span>
          );
        if (item.children) {
          return (
            <TreeNode key={item.id} title={title} dataRef={item}>
              {loop(item.children)}
            </TreeNode>
          );
        }
        return <TreeNode key={item.id} title={title} dataRef={item} />;
      });
    return (
      <Spin spinning={loading}>
        <div>
          <Search style={{ marginBottom: 8 }} placeholder="Search" onChange={this.onChange} />
          <Tree
            onExpand={this.onExpand}
            onSelect={this.onSelect}
            expandedKeys={expandedKeys}
            autoExpandParent={autoExpandParent}
          >
            {loop(treeData)}
          </Tree>
        </div>
      </Spin>
    );
  }
}

export default OrderTree;

父组件index.js代码:

import React, { Component } from 'react';
import { connect } from 'dva';
import { formatMessage, FormattedMessage } from 'umi/locale';
import { Card, Spin } from 'antd';
import PageHeaderWrapper from '@/components/PageHeaderWrapper';
import OrderForm from './components/form';
import OrderTable from './components/table';
import OrderTree from './components/tree';
import style from './style.less';
import { consoleTestResultHandler } from 'tslint/lib/test';

// let dataList = [];

@connect(({ commodity, loading, menu }) => ({
  commodity,
  loading: loading.effects['commodity/getTree'],
  menu,
}))
class OrderPage extends Component {
  constructor() {
    super();
    this.state = {
      idObject: {},
      reactFlag: false,
    };
  }
  componentDidMount() {
    const { dispatch } = this.props;
    dispatch({
      type: 'commodity/getGoodsCategory',
    });
  }
  onRef = ref => {
    this.orderForm = ref;
  };
  treeRef = ref => {
    this.orderTree = ref;
  };
  getIdObject = data => {
    this.setState(
      {
        idObject: data,
      },
      () => {
        this.orderForm.props.form.setFieldsValue({
          categoryIds: [String(data.categoryId)],
        });
        this.orderForm.inquery(data);
      }
    );
  };
  //判断是否点击重置按钮
  isReact = ref => {
    const {
      commodity: { defaultParentIdList },
    } = this.props;
    if (ref) {
      this.orderTree.setState({
        expandedKeys: defaultParentIdList,
      });
    }
  };

  render() {
    return (
      <PageHeaderWrapper logo>
        <Card bordered={false} title="商品SPU列表" className={style.antCardBox}>
          <div
            style={{ width: '350px', marginRight: '30px', boxShadow: '3px -3px 6px 0px #ccc6' }}
            className={style.antTreeBox}
          >
            <OrderTree idObject={this.getIdObject} treeRef={this.treeRef} />
          </div>
          <div style={{ flex: '1' }}>
            <OrderForm onRef={this.onRef} isReact={this.isReact} />
            <OrderTable />
          </div>
        </Card>
      </PageHeaderWrapper>
    );
  }
}

export default OrderPage;

以上就是关于antd tree 和父子组件之间的传值问题(react 总结)的详细内容,更多关于antd tree 父子组件传值的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
jQuery实现表单input中提示文字value随鼠标焦点移进移出而显示或隐藏的代码
Mar 21 Javascript
javascript获得服务器端控件的ID的实现代码
Dec 28 Javascript
jquery获取复选框被选中的值
Apr 10 Javascript
Jquery实现瀑布流布局(备有详细注释)
Jul 31 Javascript
Angularjs中使用Filters详解
Mar 11 Javascript
vue.js入门教程之基础语法小结
Sep 01 Javascript
JavaScript设计模式之单体模式全面解析
Sep 09 Javascript
jQueryUI Datepicker组件设置日期高亮
Oct 13 Javascript
JavaScript 自定义事件之我见
Sep 25 Javascript
使用Vue完成一个简单的todolist的方法
Dec 01 Javascript
详解搭建es6+devServer简单开发环境
Sep 25 Javascript
用javascript实现倒计时效果
Feb 09 Javascript
使用react+redux实现计数器功能及遇到问题
微信小程序基础教程之echart的使用
vue实现水波涟漪效果的点击反馈指令
vue 实现上传组件
May 31 #Vue.js
vue基于Teleport实现Modal组件
Vue+Element UI实现概要小弹窗的全过程
vue-cli4.5.x快速搭建项目
You might like
php实例分享之mysql数据备份
2014/05/19 PHP
Windows下安装PHP单元测试环境PHPUnit图文教程
2014/10/24 PHP
PHP解耦的三重境界(浅谈服务容器)
2017/03/13 PHP
PHP常用函数之格式化时间操作示例
2019/10/21 PHP
分析 JavaScript 中令人困惑的变量赋值
2007/08/13 Javascript
Google Map API更新实现用户自定义标注坐标
2009/07/29 Javascript
js解析与序列化json数据(三)json的解析探讨
2013/02/01 Javascript
JQuery的$命名冲突详细解析
2013/12/28 Javascript
javascript替换已有元素replaceChild()使用介绍
2014/04/03 Javascript
jQuery对JSON数据进行排序输出的方法
2015/06/24 Javascript
微信开发 微信授权详解
2016/10/21 Javascript
微信小程序自定义导航隐藏和显示功能
2017/06/13 Javascript
微信小程序页面滑动屏幕加载数据效果
2020/11/16 Javascript
基于对象合并功能的实现示例
2017/10/10 Javascript
浅谈开发eslint规则
2018/10/01 Javascript
vue-cli中vue本地实现跨域调试接口
2019/01/16 Javascript
javascript中join方法实例讲解
2019/02/21 Javascript
vue store之状态管理模式的详细介绍
2019/06/13 Javascript
Vue事件处理原理及过程详解
2020/03/11 Javascript
解决Vue-cli无法编译es6的问题
2020/10/30 Javascript
17个Python小技巧分享
2015/01/23 Python
python中WSGI是什么,Python应用WSGI详解
2017/11/24 Python
Python3 翻转二叉树的实现
2019/09/30 Python
Python子进程subpocess原理及用法解析
2020/07/16 Python
照片礼物和装饰:MyPhoto
2019/11/02 全球购物
Vrbo英国:预订度假屋
2020/08/19 全球购物
捷克建筑材料网上商店:DEK.cz
2021/03/06 全球购物
五一服装活动方案
2014/01/11 职场文书
教师研修随笔感言
2014/01/23 职场文书
2014年平安建设工作总结
2014/11/19 职场文书
捐书活动倡议书
2015/04/27 职场文书
2015年幼师工作总结
2015/04/28 职场文书
社区环境卫生倡议书
2015/04/29 职场文书
工作收入证明范本
2015/06/12 职场文书
诺贝尔奖获得者名言100句:句句启人心智,值永久收藏
2019/08/09 职场文书
MySQL悲观锁与乐观锁的实现方案
2021/11/02 MySQL