我正在開發一個 vanilla JS/jQuery 應用程式,它從會話存盤中獲取資料并將其顯示在瀏覽器中。我創建了一個“Box”類,它代表瀏覽器頁面上的一個框(即html 卡)。建構式具有各種屬性name: this.name,諸如此類。
有兩種不同型別的框——組和主題——所以我創建了兩個子類class GroupBox extends Box和class SubjectBox extends Box.
這是它的設計作業方式:在初始頁面加載時,我們呼叫一個函式displayGroupBoxes來填充新的 GroupBox。該函式回圈遍歷會話存盤中的一堆資料,并new GroupBox()在回圈的每次迭代中創建一個。在類建構式中備份,每次實體化一個新的 GroupBox 時,我們都會創建 HTML 標記來顯示資料并將它們附加到頁面。該 DOM 操作代碼位于在GroupBox類建構式中呼叫的類方法內。
還有一件事,每個 GroupBox 都有關聯的“主題”,這就是我們擁有 SubjectBox 類的原因。當用戶單擊 GroupBox 時,我們會找到關聯的 SubjectBox 物件并將它們顯示在頁面上。
好的,這里一切正常,只是我遇到了一個問題。該displayGroupBoxes()函式獲取關聯的主題并將它們傳遞回建構式以創建資料的 HTML 標記并將其附加到頁面。當所有 DOM 操作代碼都在建構式中時,我就開始作業了。然而,我收到了一位同事的代碼審查,他們說最好將 DOM 操作代碼分離到一個類方法中以提高可讀性,也就是說,它不是全部在建構式中。一旦我這樣做了,我就無法再訪問從displayGroupBoxes函式傳遞過來的資料。
我知道這里有很多非常特定于專案的代碼,但我希望通過這種解釋,有人可能能夠查看代碼并理解為什么我無法displayGroupBoxes從 GroupBox 類方法訪問函式中的屬性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()上面代碼塊中參考的函式:
// --------- 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);
}
}
}
There is a lot here but hopefully it is clear what I am trying to do. I want to pass the container, subjects, and subjectIcons properties up from this displayGroupBoxes function to the class method that creates HTML tags for the data and appends it to the page. This worked when I had all the DOM manipulation code inside the class constructor, but when I moved it outside the constructor to it's own class method for readability, everything worked except for these properties being passed up. I must be calling them wrong but I don't understand the issue.
uj5u.com熱心網友回復:
問題在于GroupBox它只定義名稱、型別和徽標的構造。您需要在類定義中添加其他屬性才能使用它們。
constructor(groupOptions) {
super({
name: groupOptions.name,
type: groupOptions.type,
logo: groupOptions.logo,
container: groupOptions.container,
subjects: groupOptions.subjects,
subjectIcons: groupOptions.subjectIcons || [],
headers: groupOptions.headers
});
uj5u.com熱心網友回復:
根據我得到的回復在此分享答案。我標記為正確的答案幾乎是正確的,除了不應在super()呼叫中傳遞屬性。我需要在類建構式中定義屬性,以便以后能夠將資料傳遞給它們displayGroupFunctions。
現在正如@Bergi 提到的,我仍然需要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();
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/367766.html
標籤:javascript html jquery oop
