【发布时间】:2021-11-29 22:59:39
【问题描述】:
我正在开发一个普通的 Javascript + jQuery 应用程序,它使用类和子类来用卡片填充浏览器,每个卡片都显示来自会话存储的数据。有一个Box 父类,然后是不同类型框的两个子类:class GroupBox extends Box 和class SubjectBox extends Box。应用程序的工作方式是,在初始页面加载时,所有组框都出现在页面上。用户可以单击组框以深入了解数据,导航到与每个组关联的主题框。
我编写了一个在页面加载时运行的函数displayGroupBoxes。它遍历会话存储中的数据,并为数据中的每个相关项生成一个new GroupBox 对象并为其分配数据中的属性。
现在,每次这个函数生成一个新的组框对象时,我都想运行另一个函数来为每个框生成 HTML 标记并将它们附加到浏览器页面。我一开始的方法是在构造函数中编写所有的 DOM 操作代码。这非常有效,但一位更有经验的开发人员向我指出,所有这些代码都应该分离到它自己的函数中。所以我创建了一个createGroupElements 函数并将DOM 操作代码移到那里。我现在从构造函数中调用该函数,以便在每次实例化新对象时运行它。
在我关于这个项目的previous S/O post 中,有人向我指出函数 " 不应该从构造函数内部调用。构造函数应该只关心设置实例属性。这样,你的子类可以在方法被调用之前完成初始化。”
我的问题是,如果不在构造函数中,我可以在哪里调用 createGroupElements 函数,以便在每次实例化新的 GroupBox 时运行一次?
相关代码见下文。
//////////////////////////////////////////////////////////////////////////////
// CLASSES \\
//////////////////////////////////////////////////////////////////////////////
//////////////////////
// Box Class (parent)
//////////////////////
/**
* 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
* @param {string} logo - Logo associated with account
*/
class Box {
constructor(boxOptions) {
this.name = boxOptions.name;
this.type = boxOptions.type;
this.logo = boxOptions.logo;
}
}
///////////////////////////
// Group SubClass
//////////////////////////
/**
* Represents a type "B" Group box. New group boxes are instantiated when the "displayGroupBoxes()" function is called.
* @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;
this.gotoGroup = groupOptions.gotoGroup;
this.container = groupOptions.container;
this.subjects = groupOptions.subjects;
this.subjectIcons = groupOptions.subjectIcons;
// Create HTML Elements and Append To Page
// ------ >>>> This should be called from outside the constructor?? <<<< ---- \\
this.createGroupBox();
}
// Function to create HTML tags and event listeners for group box elements, and append them to the page
createGroupBox() {
// Create container div for box
const newGroupBox = document.createElement("div");
newGroupBox.className = "group-box-container";
//-----> a bunch of code to create html tags and append them goes here, removed for brevity and clarity!
newGroupBox.append(mainContainer);
////////////////////////////////////////////////
// EVENT LISTENER
//////////////////////////////////////////////
// If a user clicks on a group box, we want to rebuild the page with the relevant subject boxes (drilling down in the data), similar to how a SPA application would work.
newGroupBox.addEventListener("click", () => {
// ---> a bunch of code to hide the group boxes that were on the page before, change the header, etc.
// --->> a bunch of code to generate the subject boxes (or simply toggle them to visible if they've already been created), create HTML tags, and append them to the page
// Append group box to document inside "group-boxes" container
this.container.append(newGroupBox);
}
}
//////////////////////////////////
// Subject SubClass
/////////////////////////////////
/**
* Represents a "P" type Subject Box
* @param {object} subjectOptions - An object to store our constructor args.
* @param {number} subjectId - The Subject Id associated with a given subject box.
* @param container - <div></div> element for the subject boxes to be placed in once they're instantiated.
*/
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");
}
show(isShow = true) {
if (isShow) {
$(this.container).show();
} else {
$(this.container).hide();
}
}
}
因此,实际生成新 GroupBoxes 的函数已经在 document.ready 函数内的页面加载时运行。但是 GroupBox 类方法 createGroupElements,它为每个新的组框创建 HTML 标记并将它们附加到页面,当前正在从构造函数内部调用。我该如何解决这个问题?
【问题讨论】:
-
您已经有一个在页面加载时运行的函数来创建它们。在创建每个对象后,让它调用一个函数。
标签: javascript class oop subclass