ホームページ  >  記事  >  ウェブフロントエンド  >  React の高次コンポーネントとは何ですか?ブレッドクラムナビゲーションはどのように作成されるのでしょうか?

React の高次コンポーネントとは何ですか?ブレッドクラムナビゲーションはどのように作成されるのでしょうか?

青灯夜游
青灯夜游転載
2022-10-19 19:33:211434ブラウズ

React の高次コンポーネントとは何ですか? React の上位コンポーネントを使用してブレッドクラム ナビゲーションを作成する方法について説明します。

React の高次コンポーネントとは何ですか?ブレッドクラムナビゲーションはどのように作成されるのでしょうか?

React 上位コンポーネントとは

React 上位コンポーネントは、フォーム内で変更が必要な React コンポーネントをラップしますの高階関数を呼び出し、処理が完了したら React コンポーネントを返します。 React の上位コンポーネントは、#react-routerwithRouterreact-redux## の connect など、React エコシステムで非常に頻繁に使用されます。 # 多くの API はこの方法で実装されています。

React 上位コンポーネントを使用する利点

職場では、同様の関数と重複したコンポーネント コードを含む多くのページ要件がよくあります。通常は関数を完全にコピーできます。は 1 パスのコードで実装されますが、ページの保守性が非常に悪くなり、各ページの同じコンポーネントを変更する必要があります。したがって、同じクエリ操作の結果を受け入れる、コンポーネントの外側で同じラベルをラップするなどの共通部分を抽出し、別の関数を作成し、サブコンポーネントのパラメーターとして異なるビジネス コンポーネントを渡すことができます。サブコンポーネントは変更されませんが、組み合わせによってサブコンポーネントをコンテナ コンポーネントにラップします。これは副作用のない純粋な関数であるため、これらのコンポーネントのロジックを変更せずにコードのこの部分を分離し、コードの保守性。

上位コンポーネントを自分で実装する

フロントエンド プロジェクトでは、リンク ポインティングを使用したパンくずリスト ナビゲーションが非常によく使用されますが、パンくずリスト ナビゲーションでは手動でメンテナンスが必要になるため、すべてのディレクトリ パスとディレクトリ名間のマッピングの配列。ここにあるすべてのデータは

react-router

のルーティング テーブルから取得できるため、ここからブレッドクラムの上位コンポーネントの実装を開始できます。ナビゲーション。 まず、ルーティング テーブルによって提供されるデータと、ターゲットのブレッドクラム コンポーネントに必要なデータを見てみましょう。

// 这里展示的是 react-router4 的route示例
let routes = [
  {
    breadcrumb: '一级目录',
    path: '/a',
    component: require('../a/index.js').default,
    items: [
      {
        breadcrumb: '二级目录',
        path: '/a/b',
        component: require('../a/b/index.js').default,
        items: [
          {
            breadcrumb: '三级目录1',
            path: '/a/b/c1',
            component: require('../a/b/c1/index.js').default,
            exact: true,
          },
          {
            breadcrumb: '三级目录2',
            path: '/a/b/c2',
            component: require('../a/b/c2/index.js').default,
            exact: true,
          },
      }
    ]
  }
]

// 理想中的面包屑组件
// 展示格式为 a / b / c1 并都附上链接
const BreadcrumbsComponent = ({ breadcrumbs }) => (
  <div>
    {breadcrumbs.map((breadcrumb, index) => (
      <span key={breadcrumb.props.path}>
        <link to={breadcrumb.props.path}>{breadcrumb}</link>
        {index < breadcrumbs.length - 1 && <i> / </i>}
      </span>
    ))}
  </div>
);

ここでは、ルーティング テーブルが提供するデータには 3 種類あることがわかります。ブレッドクラム コンポーネントは、現在のページのパス、ブレッドクラムに含まれるテキスト、ブレッドクラムのナビゲーション リンクを提供する必要があります。

まず、react-router が提供する withRouter 上位コンポーネント パッケージを使用します。これにより、サブコンポーネントが現在のページの location 属性を取得し、それによってページ パスを取得できるようになります。

後者の 2 つは、ルートを操作する必要があります。まず、ルートによって提供されるデータをブレッドクラム ナビゲーションに必要な形式にフラット化します。関数を使用してそれを実装できます。

/**
 * 以递归的方式展平react router数组
 */
const flattenRoutes = arr =>
  arr.reduce(function(prev, item) {
    prev.push(item);
    return prev.concat(
      Array.isArray(item.items) ? flattenRoutes(item.items) : item
    );
  }, []);

次に、フラット化されたディレクトリ パス マッピングと現在のページ パスを処理関数に入力して、ブレッドクラム ナビゲーション構造を生成します。

export const getBreadcrumbs = ({ flattenRoutes, location }) => {
  // 初始化匹配数组match
  let matches = [];

  location.pathname
    // 取得路径名,然后将路径分割成每一路由部分.
    .split('?')[0]
    .split('/')
    // 对每一部分执行一次调用`getBreadcrumb()`的reduce.
    .reduce((prev, curSection) => {
      // 将最后一个路由部分与当前部分合并,比如当路径为 `/x/xx/xxx` 时,pathSection分别检查 `/x` `/x/xx` `/x/xx/xxx` 的匹配,并分别生成面包屑
      const pathSection = `${prev}/${curSection}`;
      const breadcrumb = getBreadcrumb({
        flattenRoutes,
        curSection,
        pathSection,
      });

      // 将面包屑导入到matches数组中
      matches.push(breadcrumb);

      // 传递给下一次reduce的路径部分
      return pathSection;
    });
  return matches;
};

次に、パンくずリストのパス部分ごとにディレクトリ名を生成し、対応するルーティングの場所を指すリンク属性を付加します。

const getBreadcrumb = ({ flattenRoutes, curSection, pathSection }) => {
  const matchRoute = flattenRoutes.find(ele => {
    const { breadcrumb, path } = ele;
    if (!breadcrumb || !path) {
      throw new Error(
        'Router中的每一个route必须包含 `path` 以及 `breadcrumb` 属性'
      );
    }
    // 查找是否有匹配
    // exact 为 react router4 的属性,用于精确匹配路由
    return matchPath(pathSection, { path, exact: true });
  });

  // 返回breadcrumb的值,没有就返回原匹配子路径名
  if (matchRoute) {
    return render({
      content: matchRoute.breadcrumb || curSection,
      path: matchRoute.path,
    });
  }

  // 对于routes表中不存在的路径
  // 根目录默认名称为首页.
  return render({
    content: pathSection === '/' ? '首页' : curSection,
    path: pathSection,
  });
};

次に、render 関数が最終的な単一のブレッドクラム ナビゲーション スタイルを生成します。単一のブレッドクラム コンポーネントは、ブレッドクラムが指すパス

path

とブレッドクラム コンテンツ マッピング content の 2 つのプロパティをレンダー関数に提供する必要があります。 <pre class="brush:php;toolbar:false">/**  *  */ const render = ({ content, path }) =&gt; {   const componentProps = { path };   if (typeof content === 'function') {     return &lt;content {...componentProps} /&gt;;   }   return &lt;span {...componentProps}&gt;{content}&lt;/span&gt;; };</pre>これらの関数を使用すると、現在のパスとルーティング属性をラップされたコンポーネントに渡すことができる React の上位コンポーネントを実装できます。コンポーネントを渡して、新しい同一のコンポーネント構造を返すことで、コンポーネントの外部の機能や操作が損なわれることはありません。

const BreadcrumbsHoc = (
  location = window.location,
  routes = []
) => Component => {
  const BreadComponent = (
    <Component
      breadcrumbs={getBreadcrumbs({
        flattenRoutes: flattenRoutes(routes),
        location,
      })}
    />
  );
  return BreadComponent;
};
export default BreadcrumbsHoc;

この上位コンポーネントを呼び出す方法も非常に簡単で、現在のパスと

react ルーター#全体によって生成された

routes 属性を渡すだけです。 ##。 現在のパスの取得方法は、react router が提供する
withRouter 関数を利用することができますので、使用方法については関連ドキュメントを参照してください。 withRouter 自体は、ラップされたコンポーネントの
location 属性を含むいくつかのルーティング属性を提供できる上位コンポーネントであることに言及する価値があります。したがって、この API は、高次コンポーネントを学習するための優れたリファレンスとしても使用できます。

withRouter(({ location }) =>
  BreadcrumbsHoc(location, routes)(BreadcrumbsComponent)
);
Q&A

    react router
  • によって生成された

    routes が独自に手動で保守されていない場合、ローカルに存在しますが、リクエストを通じてプルされ、redux に保存されます。react-redux によって提供される connect 高階関数を通じてラップされると、ルートによってパッケージが変更されることはありません. クラムコンポーネントが更新されました。使用法は次のとおりです。

    function mapStateToProps(state) {
      return {
        routes: state.routes,
      };
    }
    
    connect(mapStateToProps)(
      withRouter(({ location }) =>
        BreadcrumbsHoc(location, routes)(BreadcrumbsComponent)
      )
    );
  • これは、実際には
connect
関数の

bug です。 React-redux の接続上位コンポーネントは、受信パラメータ コンポーネントの shouldComponentUpdate フック関数を実装するため、更新関連のライフ サイクル関数 (レンダリングを含む) は、プロップが変更された場合にのみトリガーされます、そして明らかに、 location オブジェクトはパラメータ コンポーネントに prop として渡されません。 公式に推奨されるアプローチは、withRouter を使用して

connect

戻り値、つまり をラップすることです。<pre class="brush:php;toolbar:false">withRouter(   connect(mapStateToProps)(({ location, routes }) =&gt;     BreadcrumbsHoc(location, routes)(BreadcrumbsComponent)   ) );</pre> <p>其实我们从这里也可以看出,高阶组件同高阶函数一样,不会对组件的类型造成任何更改,因此高阶组件就如同链式调用一样,可以任意多层包裹来给组件传入不同的属性,在正常情况下也可以随意调换位置,在使用上非常的灵活。这种可插拔特性使得高阶组件非常受React生态的青睐,很多开源库里都能看到这种特性的影子,有空也可以都拿出来分析一下。</p>

以上がReact の高次コンポーネントとは何ですか?ブレッドクラムナビゲーションはどのように作成されるのでしょうか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はcnblogs.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。