簡體   English   中英

在JavaScript中遞歸添加object到數組

[英]Add object to array recursively in JavaScript

我正在通過 Contentful API 處理數據,我正在嘗試構建我正在構建的網站的結構。 我正在使用 GraphQL API 並獲取 Contentful 頁面,但是,由於速率限制,在獲取引用和層次結構時,我不能 go 超深查詢。

這讓我查詢我的“頁面”內容類型並獲取每個頁面並獲取其父頁面 ID,僅向上一級。 理論是,如果我對每個頁面都這樣做,我可以通過在構建期間運行一些 JS 來遞歸地構建頁面結構(我正在使用 Eleventy 構建站點)。

我需要一個 function 來為我生成一個面包屑數組,理想情況下,我會為 function 提供一個頁面的 ID,它會跟蹤數據以獲取父項、父項的父項等的詳細信息,直到沒有更多的父項為止。

我有以下代碼,目前分為兩個函數(雖然不確定這是否是最好的方法!)

  /**
   * This takes an ID and finds it within the contentfulPages array (the result
   * of the GraphQL query to Contentful)
   * It returns an object containing the page's ID, slug (for the URL), title
   * (for the readable text) and the parentPageId so we can use that to get the
   * same details for the parent page
   */
  function getParentPage(pageId) {
    const { id, slug, title, parentPageId } = contentfulPages.find(
      (page) => page.id === pageId
    );
    return { id, slug, title, parentPageId };
  }

  /**
   * This takes an ID and passes it to getParentPage to get the first parentPage
   * details. If there is another parent page, it calls itself with the newly 
   * found parent page and pushes that object to the breadcrumbArray. Because it
   * returns the breadcrumb array, each iteration is a more deeply nested array 
   * as opposed to an object at the same level
   */
  function getBreadcrumb(pageId) {
    let breadcrumbArray = [];
    const { id, slug, title, parentPageId } = getParentPage(pageId);
    breadcrumbArray.push({ id, slug, title, parentPageId });
    if (parentPageId) {
      breadcrumbArray.push(getBreadcrumb(parentPageId));
    }
    return breadcrumbArray;
  }

我明白為什么它在做它正在做的事情,但我不知道如何修復它——我希望最終結果是一個平面對象數組,但我認為遞歸 function 給我帶來了問題,因為我認為它有返回一些東西,但我不知道該怎么做!

三層深度頁面的示例如下:

// Expected:
[
  {
    id: 'page-3',
    slug: 'courses',
    title: 'Courses',
    parentPageId: 'page-2'
  },
  {
    id: 'page-2',
    slug: 'training',
    title: 'Training',
    parentPageId: 'page-1'
  },
  {
    id: 'page-1',
    slug: 'services',
    title: 'Services',
    parentPageId: false
  },
]


// Actual:
[
  {
    id: 'page-3',
    slug: 'courses',
    title: 'Courses',
    parentPageId: 'page-2'
  },
  [
    {
      id: 'page-2',
      slug: 'training',
      title: 'Training',
      parentPageId: 'page-1'
    },
    [ 
      {
        id: 'page-1',
        slug: 'services',
        title: 'Services',
        parentPageId: false
      },
    ]
  ]
]

協助將不勝感激!

與其將getBreadcrumb中的整個返回數組推送到結果中,不如使用擴展語法 ( ... )推送返回數組中的各個數組元素:

breadcrumbArray.push(...getBreadcrumb(parentPageId))

請注意,如果getBreadcrumb()返回的數組非常大並且超過了可以傳遞給.push()的最大參數計數,則上述操作將失敗 function。您始終可以選擇執行當前正在執行的操作,然后在返回的結果上調用.flat(Infinity) 這確實會增加對陣列的額外傳遞,但這是可以避免的。 您可以通過返回一個新數組來克服這些問題,並將返回的數組散布到該數組中:

function getBreadcrumb(pageId) {
  const { id, slug, title, parentPageId } = getParentPage(pageId);
  return [{ id, slug, title, parentPageId }, ...(parentPageId ? getBreadcrumb(parentPageId) : [])];
}

上面的代碼將創建一個新數組,將您的{id, slug, ...} object 作為第一個元素,后跟任何內容(如果parentPageId為假),或者調用getBreadcrumb(parentPageId) )

這是一種非遞歸方法,使用while循環,然后重新調用getParentPage()

 function getBreadcrumb(pageId) { let breadcrumbArray = []; let { id, slug, title, parentPageId } = getParentPage(pageId); breadcrumbArray.push({ id, slug, title, parentPageId }); // while parentPageId === false, execute getParentPage with found id while ( parentPageId ) { pageObj = getParentPage(id); breadcrumbArray.push(pageObj); // update found id and parentPageId for while loop id = pageObj.parentPageId; parentPageId = pageObj.parentPageId; } return breadcrumbArray; } // okay to ignore the rest... // parent page mock up, randomly return a parentPageId that equates to false function getParentPage(pageId) { return { id: 1, slug: "slug", title: "title", parentPageId: Math.floor(Math.random() * 2) }; } console.log(getBreadcrumb(3));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM