首页 > 解决方案 > 反应父组件从开关/路由中获取渲染元素的计数

问题描述

我正在尝试制作一个组件来呈现其子元素的包装器元素,但是它需要知道元素是否被呈现为其子元素。我有忽略 Switch、Route 和组件子组件的功能。

const MAX_CHILDREN_TRAVERS = 8;
const NON_RENDABLE_ELEMENTS = ['Switch','Switch()','Route','LeftPanel','MainPanel','RightPanel'];

function findByType (children, component) {
  return children === undefined || children.length === 0 ? null : children.filter(child => component.name === getElmType(child));
};

function getElmType(elm) {
  return elm && elm.type && (elm.type.displayName || elm.type.name);
}

function getRendableChildren(elm) {
  const checkChildren = (e, count) => {
    if(count>MAX_CHILDREN_TRAVERS) {
      return e;
    }
    return NON_RENDABLE_ELEMENTS.includes(getElmType(e)) ? checkChildren(e.props.children,count++) : e;
  };
  return elm.length > 0 ? elm.map(elm => checkChildren(elm,0)) : elm;
}

function renderPanel({ children, panel, className}) {
  const myPanel = findByType(children, panel);
  return getRendableChildren(myPanel).length > 0 || myPanel === null || myPanel.length === 0 ? null : <div className={className}>{myPanel.map(el => el.props.children)}</div>;
};

export {
  findByType,
  renderPanel
};

这确实返回忽略列出元素的子元素数组。但是,它也会为我提供路径中未在该路径上呈现的元素。我只想要在该路线上呈现的元素列表。

getRendableChildren() 应该遍历直到找到可读元素并返回它们。虽然它适用于忽略和传递我想忽略的列出的元素。无论路由是否处于活动状态,它都可以看到所有路由中的所有子元素。

标签: javascriptreactjs

解决方案


我发现如果我使用 window.location.pathname 并将其检查到 Route e.props.path。我可以确认路线是否处于活动状态并根据需要排除。

import React from 'react';
const MAX_CHILDREN_TRAVERS = 8;
const NON_RENDABLE_ELEMENTS = ['Switch','Switch()','LeftPanel','MainPanel','RightPanel'];
const IS_ROUTE = ['Route','Route()'];

function findByType (children, component) {
  return children === undefined || children.length === 0 ? null : children.filter(child => component.name === getElmType(child));
};

function getElmType(elm) {
  return elm && elm.type && (elm.type.displayName || elm.type.name);
}

function getRendableChildren(elm) {
  const checkChildren = (e, count) => {
    if(count>MAX_CHILDREN_TRAVERS) {
      return e;
    }
    const elmType = getElmType(e);
    if(IS_ROUTE.includes(elmType)){
      const lo = window.location.pathname.split('/').filter(a => a.length);
      const pa = e.props.path.split('/').filter(a => a.length);
      return pa.every((e,i) => e === lo[i]) ? [...e.props.children] : null;
    }
    return NON_RENDABLE_ELEMENTS.includes(elmType) ? checkChildren(e.props.children,count++) : e;
  };
  return elm.length > 0 ? elm.map(elm => checkChildren(elm,0))[0] : elm;
}

function renderPanel({ children, panel, Wrapper, props}) {
  const myPanel = findByType(children, panel);
  return getRendableChildren(myPanel) === null || getRendableChildren(myPanel).length === 0 || myPanel === null || myPanel.length === 0 ? null : React.createElement(Wrapper, props, myPanel.map(el => el.props.children));
};

export {
  findByType,
  renderPanel
};

推荐阅读