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

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

写了三个组件:

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

现在可以分部解决问题:

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

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

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

4.form组件中的inquery方法:

现附上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 父子组件传值的资料请关注编程宝库其它相关文章!

JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程 ...