你可能不知道的children(React)

  一、我以为的children

   children嘛,child的复数形式,所以顾名思义,某个组件的children(this.props.children/props.children)其实就是这个组件的子组件,表现在代码中,无非就是(如下简易演示demo)

     

<Parent>

 <Child1></Child1>
 <Child2></Child2>
    ...
 <Childn></Childn>
</Parent>

在parent组件中获取到的children就是 {Child1,Child2,....Childn}

二、项目需求

实际开发中遇到了一个挺合理的需求,但是前端真的是束手无策,描述如下:

某个页面PageA,在PageA触发跳转到PageB页面,要求如下:

1、pageA——>PageB——>pageA:pageA页面的查询条件需要保存(如果有的话),即就是在pageA以某个条件进行筛选查询后进入PageB再进入pageA,此时pageA应该保存在跳转之前的状态(数据、查询条件);

2、pageA进入其他页面(即就是通过切换菜单栏切换页面)后再回来不需要保存之前的状态(eg:pageA进入pageC再回到pageA,此时pageA应该恢复初始默认时的状态,即不保存查询条件)

现状:

    项目用的是ant中的pro4脚手架搭建(https://pro.ant.design/index-cn),内部数据使用dva的Redux进行管理,所以所有的查询条件都会被保存到redux中(用户不强制刷新页面的话),导致,无论何种切换(跳)页面,数据(查询条件始终被保存)

解决思路:

   在组件销毁的生命周期(componentWillUnmount)中,清空该页面的所有存在redux中的数据(一般是在项目model层,写一个方法)

遗留问题:

  解决了页面跳转不保存数据(查询条件)的问题,但是用户在某个页面内点击进入到另一个页面再回来的场景(需要保存数据)

解决思路2:

     在组件销毁的生命周期(componentWillUnmount)中,分情况清空该页面的所有存在redux中的数据,本次需求即就是在从页面中点击后跳转再回去

if(从页面中点击跳转再回去){

    保存之前数据

}else{  

    不保存数据即就是清空数据

}

遇到问题:

      怎么判断用户是从页面中点击后跳转的呢?我想到了监听回退事件,再回退事件中重新对redux中的变量赋值,but,这个听起来就很复杂,如何 监听?重新对redux中的变量赋值,这听起来就很复杂

同事思路:

     同事说他们之前遇到过这种需求,是通过将组建绑定到一个“入口文件”中来实现的,具体思路:

     A、将需要保存数据的相关页面(组件)集中到一个入口文件;

     B、在入口组件销毁的生命周期方法中清空数据

   一点小小解释:

           可以简单理解为:需要保留数据的页面(组件)之间有一个共同的父组件,在父组件销毁的生命周期方法中清空数据(需要保留数据的页面切换时,不会调用父组件销毁的生命周期方法,只有在非相关页面(没有数据关联的页面)页面切换时才会调用销毁方法,清空数据)

分析继续:

   感觉思路没啥问题,问题就在于

    1、平白无故多出一个组件,还是两个页面的父组件,这个父组件路由怎么配置,这难道不仅仅是多出一个组合两个页面在一起的页面?

  2、同事之前的代码是pro1,版本太老旧了,而且还用到一些工具类,看不懂

思路受阻,前辈代码又看不懂……但是有一点是肯定的,他们之前确实用这种方法实现了这种需求,虽然看不懂实现的细节,但是还是可以看看代码结构什么的,于是……

父组件(入口文件)代码结构如下:

import React, { PureComponent, Fragment } from 'react';
import { connect } from 'dva';
import { Route, Redirect, Switch } from 'dva/router';
import NotFound from '../../Exception/404';
import { getRoutes } from '../../../utils/utils';

@connect()
export default class XXXWrap extends PureComponent {
  componentWillUnmount() {
    this.props.dispatch({
      type: 'xx/save',
      payload: {
        xxx: {},
      },
    });
  }

  render() {
    const { match, routerData } = this.props;
    return (
      <Fragment>
        <Switch>
          {getRoutes(match.path, routerData).map(item => (
            <Route key={item.key} path={item.path} component={item.component} exact={item.exact} />
          ))}
          <Redirect exact from="/xx/service" to="/xx/service/yy" />
          <Route render={NotFound} />
        </Switch>
      </Fragment>
    );
  }
}

突然有了一点发现:

    这个所谓的入口组件,内容都是Route哎,也就是说入口组件通过Router将其他组件“包”在一起的

这是有疑问:

     这个入口组件的路由怎么配?pro1的配置方法太麻烦了,不想看……

同事也在研究,发现Pro2版本同样的地方(List.js)中放弃了pro1版本的写法,而是直接使用children

路由怎么配,看代码:在路由文件中,搜索/List/List,还真被我找到了

  原来它是把入口文件在路由配置文件中,作为component

   运行代码找到对应页面:

研究了一下发现:

   这根本不是我想要的效果呀,虽然它还是多出了一个页面来将子页面整合到一起……

不对!在List中没有啥问题,但是其他页面也没有将List作为父组件,怎么会是List的children?难道,children不仅仅是代码结构上嵌套表现出来的子组件,路由配置中只要某个组件中routes的组件,都是这个组件的children!好像讲得通!

在这种思路的引导下,我整理出新的代码,如下:

import React, { Component, Fragment } from 'react';
import { connect } from 'dva';
import { Dispatch } from 'redux';

interface IXXIndexProps {
  dispatch: Dispatch;
}
@connect()
class XXIndex extends Component<IXXIndexProps > {
  componentWillUnmount(): void {
   /*
    *
    销毁redux中数据的逻辑
   */
  }

  render() {
    const { children } = this.props;

    return <Fragment>{children}</Fragment>;
  }
}

export default XXIndex ;

在路由文件中配置如下:

{
      path: '/xx/yy',
      name: 'll',
      hideChildrenInMenu: true,
      component: './xx/XXIndex.tsx',
      routes: [
        {
         path: '/xx/yy',
           name: 'll',
          component: './xx/XXAnalysis',
        },
        {
          path: '/xx/pageA',
          component: './xx/pageA',
        },
        {
          path: '/xx/pageB',
          component: './xx/pageB',
        },
      ],
    },

然后

    问题成功的解决了

感觉废话有点多,但这确实是发现并解决这个问题坎坷的血泪史,真的是柳暗花明又一村呀!

--------------------------------干货整理----------------------------------------------------

需求:

   点击菜单栏跳转,不需要保留页面查询条件;页面内部跳转再回去,需要保留页面查询条件

解决思路:

   ①将需要保留查询条件的相关页面使用一个入口文件“包裹”;②、在路由文件中,将入口文件设置为routes(包含了相关页面路由)同级别的component

你可能不知道的children:

   router配置文件中,在routes中路由对应的文件,自动作为组件的children

eg:

     

{
      path: '/a/b',
      name: 'xx',
      hideChildrenInMenu: true,
      component: './a/b/ParenntIndex',
      routes: [
        {
          path: '/l/cc',
          name: 'l-cc',
          component: './l/PageA',
        },
        {
          path: '/l/cc/dd',
          component: './l/cc/PageB',
        },
        {
          path: '/l/cc/ff',
          component: './l/PageC',
        },
      ],
    },

在ParenntIndex获取children,则就是{PageA,PageB,PageC}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值