关于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 父子组件传值的资料请关注我们其它相关文章!

(0)

相关推荐

  • React父子组件间的传值的方法

    父组件向子组件传值: 父组件: import React, { Component } from 'react'; import Child from './chlid'; class parent extends Component{ constructor(props) { super(props); this.state = { txt0:"默认值0", txt1:"默认值1" } } componentDidMount(){ } parToson(){ th

  • React 子组件向父组件传值的方法

    本文介绍了React 子组件向父组件传值的方法,分享给大家 子组件需要控制自己的 state, 然后告诉父组件自己的state,通过props调用父组件中用来控制state的函数,在父组件中展示子组件的state变化. /***实现在输入框输入邮箱时,在div中即时显示输入内容***/ <body> <div id="test"></div> </body> //子组件 var Child = React.createClass({ re

  • react 组件传值的三种方法

    整理 react 组件传值 三种方式 父组件向子组件传值(通过props传值) 子组件: class Children extends Component{ constructor(props){ super(props); } render(){ return( <div>这是:{this.props.name}</div> // 这是 父向子 ) } } 父组件: class App extends React.Component{ render(){ return( <

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

    项目需求:点击产品树节点时获取该节点的所有父节点,同时回填表格的搜索条件,完成搜索功能,搜索结果展示在下方的table中. 写了三个组件: 现在有个业务场景交互:在orderTree组件中点击树节点,获取当前节点以及所有的父节点的Id 放入一个对象arrKeys中,并在orderForm组件中使用(回填类型下拉选择框,objId对象作为查询接口的入参) 现在可以分部解决问题: 1.首先获取点击的树节点以及所有父节点的id ---arrKeys 2.在点击树节点获取当前节点以及所有父级节点之后,通

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

    项目需求:点击产品树节点时获取该节点的所有父节点,同时回填表格的搜索条件,完成搜索功能,搜索结果展示在下方的table中. 写了三个组件: 现在有个业务场景交互:在orderTree组件中点击树节点,获取当前节点以及所有的父节点的Id 放入一个对象arrKeys中,并在orderForm组件中使用(回填类型下拉选择框,objId对象作为查询接口的入参) 现在可以分部解决问题: 1.首先获取点击的树节点以及所有父节点的id ---arrKeys 2.在点击树节点获取当前节点以及所有父级节点之后,通

  • vue组件之间进行传值的方法

    目录 前言 1.父组件向子组件进行传值 2.子组件向父组件进行传值 3.非父子组件之间的传值 总结 前言 目前在做vue的项目,用到了子组件依赖其父组件的数据,进行子组件的相关请求和页面数据展示,父组件渲染需要子组件通知更新父组件的state,父子组件之间的传值一般有三种方法: 父传子子传父非父子传值 注意: 父子组件的关系可以总结为 prop 向下传递,事件向上传递.父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息.  接下来,我们会通过实例代码来看的更清晰,理解更容易:

  • 通过实例讲解vue组件之间的传值

    目录 前言 1.父组件向子组件进行传值 2.子组件向父组件进行传值 3.非父子组件之间的传值 总结 前言 目前在做vue的项目,用到了子组件依赖其父组件的数据,进行子组件的相关请求和页面数据展示,父组件渲染需要子组件通知更新父组件的state,父子组件之间的传值一般有三种方法: 父传子 子传父 非父子传值 注意: 父子组件的关系可以总结为 prop 向下传递,事件向上传递.父组件通过 prop 给子组件下发数据,子组件通过事件给父组件发送消息. 接下来,我们会通过实例代码来看的更清晰,理解更容易

  • vue2.0父子组件及非父子组件之间的通信方法

    1.父组件传递数据给子组件 父组件数据如何传递给子组件呢?可以通过props属性来实现 父组件: <parent> <child :child-msg="msg"></child>//这里必须要用 - 代替驼峰 </parent> data(){ return { msg: [1,2,3] }; } 子组件通过props来接收数据: 方式1: props: ['childMsg'] 方式2 : props: { childMsg: Arr

  • vuejs父子组件之间数据交互详解

    父子组件之间的数据交互遵循: props down - 子组件通过props接受父组件的数据 events up - 父组件监听子组件$emit的事件来操作数据 示例 子组件的点击事件函数中$emit自定义事件 export default { name: 'comment', props: ['issue','index'], data () { return { comment: '', } }, components: {}, methods: { removeComment: funct

  • Vue父子组件之间的通信实例详解

    在vue组件通信中其中最常见通信方式就是父子组件之中的通信,而父子组件的设定方式在不同情况下又各有不同.最常见的就是父组件为控制组件子组件为视图组件.父组件传递数据给子组件使用,遇到业务逻辑操作时子组件触发父组件的自定义事件.无论哪种组织方式父子组件的通信方式都是大同小异. 一.父组件到子组件通讯 父组件到子组件的通讯主要为:子组件接受使用父组件的数据,这里的数据包括属性和方法(String,Number,Boolean,Object, Array ,Function).vue提倡单项数据流,因

  • vue实现父子组件之间的通信以及兄弟组件的通信功能示例

    本文实例讲述了vue实现父子组件之间的通信以及兄弟组件的通信功能.分享给大家供大家参考,具体如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>www.jb51.net vue父子组件通信.兄弟组件通信</title> <style> *{ margin: 0; padding: 0; l

  • vuejs中父子组件之间通信方法实例详解

    本文实例讲述了vuejs中父子组件之间通信方法.分享给大家供大家参考,具体如下: 一.父组件向子组件传递消息 // Parent.vue <template> <div class="parent"> <v-child :msg="message"></v-child> </div> </template> <script> import VChild from './child.v

  • Vue非父子组件之间的通信方式详解

    目录 非父子组件的通信 1.Provide和Inject 1.1基本使用 1.2处理响应式数据(了解) 2.全局事件总线 总结 非父子组件的通信 此篇讲解的是, 在学习状态管理之前, 非父子间通信的方案 在开发中,我们构建了组件树之后,除了父子组件之间的通信之外,还会有非父子组件之间的通信. 这里我们主要讲两种方式: Provide/Inject: 全局事件总线: 1.Provide和Inject 1.1基本使用 Provide/Inject用于非父子组件之间共享数据: 比如有一些深度嵌套的组件

随机推荐