簡體   English   中英

Javascript,如何將屬性從方法傳遞到 class 構造函數?

[英]Javascript, how can I pass properties from method up to class constructor?

我正在開發一個普通的 JS / jQuery 應用程序,該應用程序從 session 存儲中獲取數據並將其顯示在瀏覽器中。 我在瀏覽器頁面上創建了一個“盒子”class,它代表一個盒子(即html卡)。 構造函數具有各種屬性,例如name: this.name等等。

有兩種不同類型的框 - Group 和 Subject - 所以我創建了兩個子類class GroupBox extends Boxclass SubjectBox extends Box

這是它的設計工作方式:在初始頁面加載時,我們調用 function displayGroupBoxes來填充新的 GroupBoxes。 function 循環遍歷 session 存儲中的一堆數據,並在循環的每次迭代中創建一個new GroupBox() 在 class 構造函數中備份,每次實例化一個新的 GroupBox 時,我們都會創建 HTML 標簽來顯示數據,並在頁面上顯示 append。 該 DOM 操作代碼位於GroupBox class 方法中,該方法在 class 構造函數中調用。

還有一件事,每個 GroupBox 都有關聯的“主題”,這就是我們有 SubjectBox class 的原因。 當用戶單擊 GroupBox 時,我們會找到關聯的 SubjectBox 對象並將它們顯示在頁面上。

好的,所以一切都在這里工作,除了我遇到了一個問題。 displayGroupBoxes() function 抓取關聯的主題並將它們傳遞回構造函數,為數據創建 HTML 標記,並將 append 標記到頁面。 當所有 DOM 操作代碼都在構造函數中時,我得到了這個工作。 然而,我收到了一位同事的代碼審查,他們說最好將 DOM 操作代碼分離到 class 方法中以提高可讀性,也就是說,它並不全部在構造函數中。 完成此操作后,我將無法再訪問從displayGroupBoxes function 傳遞的數據。

我知道這里有很多非常特定於項目的代碼,但我希望通過這種解釋,有人可能能夠查看代碼並理解為什么我無法從 GroupBox class 訪問displayGroupBoxes function 中的屬性方法createNewElements

//////////////////////////////////////////////////////////////////////////////
//  CLASSES \\
//////////////////////////////////////////////////////////////////////////////

/////////////////////////
// BOX Parent Class
/////////////////////////

/**
 * Represents a box.
 * @constructor
 * @param {object} boxOptions - An object to hold our list of constructor args
 * @param {string} name - Name associated with account
 * @param {string} type - Type associated with account
 */
class Box {
  constructor(boxOptions) {
    this.name = boxOptions.name;
    this.type = boxOptions.type;
    this.logo = boxOptions.logo;
  }
}

/////////////////////////////
// SubjectBox SubClass
////////////////////////////

/**
 * Represents a SubjectBox. These are subjects, like individual people, associated with a given group. We don't see these on initial page load. They get created (or if already created, toggled to hidden/visible) when a user clicks on a group.
 */

class SubjectBox extends Box {
  constructor(subjectOptions) {
    super({
      name: subjectOptions.name,
      type: subjectOptions.type,
      logo: subjectOptions.logo,
    });
    this.name = subjectOptions.name;
    this.type = subjectOptions.type;
    this.logo = subjectOptions.logo;
    this.subjectId = subjectOptions.subjectId;
    this.container = document.createElement("div");

// ---> a bunch of code to create HTML tags and append to page
}

/////////////////////////
// GroupBox SubClass
/////////////////////////

/**
 * Represents a GroupBox. New group boxes are instantiated when the "displayGroupBoxes()" function is called. This is what we see on initial page load.
 * @constructor
 * @param {object} groupOptions - An object to store our list of constructor args
 * @param {array} subjectBoxes - An array to store subject boxes so that once they've been instantiated, we can store them here and then toggle to hidden/visible.
 */

class GroupBox extends Box {
  constructor(groupOptions) {
    super({
      name: groupOptions.name,
      type: groupOptions.type,
      logo: groupOptions.logo,
    });

// Use this array to store the subject boxes that have already been created, so if the user clicks on the same subject, we can grab those boxes and show them rather than rebuilding.

    this.subjectBoxes = [];
    this.name = groupOptions.name;
    this.type = groupOptions.type;
    this.logo = groupOptions.logo;

    // Create HTML Elements and Append To Page

    this.createGroupBox();
  }

  // Class method to create HTML tags and append to page

  createGroupBox() {
    // Create container div for box
    const newGroupBox = document.createElement("div");
    newGroupBox.className = "group-box-container";

    // ----> A bunch of code here to create name and title, append to page. Now we need to display image icons of the subjects that are associated with the group:

    // Container for SubjectBox Icons
    const mainContainer = document.createElement("div");
    mainContainer.className = "box-main-container";

    // Icons
    const iconsContainer = document.createElement("div");
    iconsContainer.className = "box-icons-container";

    // Loop through Icons object, which contains arrays of subjects, to create an img tag for each one and append to iconsContainer.

   //// ------ >> this.subjectIcons is now returning undefined << \\


    let icons = this.subjectIcons;
    for (let i in icons) {
        let iconDiv = document.createElement("div");
        iconDiv.className = "box-icon-div";
        let icon = document.createElement("img");
        icon.src = icons[i];
        icon.className = "box-icon";
        iconDiv.append(icon);
        iconsContainer.append(iconDiv);
        mainContainer.append(iconsContainer);
        i++;
    }

    newGroupBox.append(mainContainer);

/////////////////////////////////////////////////////////////////
    // EVENT LISTENER. -- when the user clicks on a GroupBox, it runs a function to show us the subjects associated with that group
////////////////////////////////////////////////////////////////

    newGroupBox.addEventListener("click", () => {
      /// --> some code to hide the GroupBoxes that are already on the page so we can display SubjectBoxes instead

      // build subject boxes
      const boxesContainer = document.getElementById("boxes-container");

      // Check to see if subject boxes have already been created. If not, instantiate the new subjectBox objects. Otherwise, if they have already been built, loop through and set them to visible

      if (!this.subjectBoxes.length) {

// If subject boxes haven't been created yet, meaning if the user hasn't clicked on this group yet, map over the array of subjects passed up from the `displayGroupBoxes()` function and create a `new SubjectBox` object for each item

     //! -----> groupOptions.subjects is returning undefined << \\

        this.subjectBoxes = groupOptions.subjects.map((subject, i) => {
          return new SubjectBox({
            name: groupOptions.subjects[i].entry_text,
            type: groupOptions.subjects[i].entry_type,
            logo: groupOptions.subjects[i].icon_link,

            subjectId: groupOptions.subjects[i].subject_id,

            // Set the container for HTML
            container: boxesContainer,
          });
        });

// Otherwise if subject boxes have already been created previously, toggle them to visible
      } else {
        for (const box of this.subjectBoxes) {
          box.show();
        }
      }

    // Append group box to document inside the same container we created for GroupBoxes:

// -------> groupOptions.container is returning undefined ----- \\

    groupOptions.container.append(newGroupBox);
  }
}


這是上面代碼塊中引用的displayGroupBoxes() function:

// --------- Populate Group Boxes --------- \\

function displayGroupBoxes() {
  // Initialize array to hold collection of group boxes
  let groupBoxes = [];

  // Grab the "boxes-container" div from HTML and set it to variable "boxesContainer"
  const boxesContainer = document.getElementById("boxes-container");

  // Loop through the data to grab all the "B" type group boxes
  // Create a new GroupBox object for each item in the array

  
  for (let arr in data) {
    if (data[arr].entry_type === "B") {
      // Find all "Subject" ("P") boxes associated with item and store in variable "subjectGroup". Then grab all the icon image URL's
      
      let subjectGroup = data.filter(
        (group) =>
          group.group_number === data[arr].goto_group &&
          group.entry_type === "P"
      );

      let subjectGroupIcons = [];
      for (let i in subjectGroup) {
        if (
          subjectGroup[i].group_number === data[arr].goto_group &&
          subjectGroup[i].entry_type === "P"
        ) {
          subjectGroupIcons.push(subjectGroup[i].icon_link);
        }
      }


      // Create new GroupBox objects
      let groupBox = new GroupBox({
        name: data[arr].entry_text,
        type: data[arr].entry_type,
        logo: data[arr].icon_link,
       

        //! I'm not able to access these from the new "createGroupBoxes" function...

        // Set the container for HTML
        container: boxesContainer,
        // Pass subjects to GroupBox
        subjects: subjectGroup,
        // Pass subject icons up to GroupBox
        subjectIcons: subjectGroupIcons,
        // Pass headers (e.g. "Tennis Group") up to GroupBox
        headers: headerGroup,
      });

      // Push each groupBox object into the groupBoxes array.
      // This is just for convenience so we can see all the group boxes easily if we need to.
      groupBoxes.push(groupBox);
    }
  }
}

這里有很多東西,但希望很清楚我想要做什么。 我想將此displayGroupBoxes function 中的containersubjectIcons subjects傳遞給 class 方法,該方法為數據創建 HTML 標記並將其附加到頁面。 當我在 class 構造函數中擁有所有 DOM 操作代碼時,這很有效,但是當我將它移到構造函數之外時,為了便於閱讀,一切正常,除了這些屬性被傳遞。 我一定是把他們叫錯了,但我不明白這個問題。

問題出在GroupBox構造中,它僅定義名稱、類型和徽標。 您將需要在 class 定義中添加其他屬性,以便它們可用。

  constructor(groupOptions) {
    super({
      name: groupOptions.name,
      type: groupOptions.type,
      logo: groupOptions.logo,
      container: groupOptions.container,
      subjects: groupOptions.subjects,
      subjectIcons: groupOptions.subjectIcons || [],
      headers: groupOptions.headers
    });

根據我得到的回復在這里分享答案。 我標記為正確的答案幾乎是正確的,除了屬性不應在super()調用中傳遞。 我需要在 class 構造函數中定義屬性,以便稍后能夠從displayGroupFunctions向它們傳遞數據。

現在正如@Bergi 提到的,我仍然需要從構造函數外部調用 class 方法createGroupBox ,但以下代碼解決了我原來的問題:

class GroupBox extends Box {
  // PARAM: groupOptions = {}
  constructor(groupOptions) {
    super({
      name: groupOptions.name,
      type: groupOptions.type,
      logo: groupOptions.logo,
    });
    // Use this array to store the subject boxes that have already been created, so if the user clicks on the same subject, we can grab those boxes and show them rather than rebuilding.
    this.subjectBoxes = [];
    this.name = groupOptions.name;
    this.type = groupOptions.type;
    this.logo = groupOptions.logo;

 -----> new code:
    this.container = groupOptions.container;
    this.subjects = groupOptions.subjects;
    this.subjectIcons = groupOptions.subjectIcons;
    this.headers = groupOptions.headers;

----> this should be called from outside the constructor 

    // Create HTML Elements and Append To Page
    this.createGroupBox();
  }

暫無
暫無

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

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