设计在 DOM 中表示 UI 对象的 JavaScript 类的最佳实践是什么?

发布于 2024-11-18 05:58:53 字数 2367 浏览 5 评论 0原文

我非常熟悉 JavaScript 和 OOP,但非常不熟悉设计用于 UI (HTML) 编程的 JS 类。我进行了一些搜索,但没有发现任何流行的模式。

假设我想动态创建类似面板的对象(类似于 Microsoft Windows 面板)。每个对象都需要一个容器、一个可能包含文本标签的标题区域以及一个具有单击事件处理程序的关闭按钮。除了 DOM 表示 (HTML) 之外,该对象还具有 JavaScript 对象表示(变量和方法)。这是我尝试过的一种方法:

//
// Window class
//
var Window = function(params) {
    this.testMethod = function() {
        console.log('test');  // just an example
    }

    this.windowDiv = document.createElement('div');
    this.windowDiv.style.width = params.width + 'px';
    this.windowDiv.style.height = params.height + 'px';
    this.windowDiv.style.position = 'absolute';
    this.windowDiv.style.top = '30px';
    this.windowDiv.style.left = '30px';
    this.windowDiv.style.border = '1px solid #000';

    this.headerDiv = document.createElement('div');
    this.headerDiv.style.width = '100%';
    this.headerDiv.style.height = '30px';
    this.headerDiv.style.background = '#bbb';
    this.headerDiv.style.borderBottom = '1px solid #000';
    this.headerDiv.innerHTML = params.title;

    this.buttonDiv = document.createElement('div');
    this.buttonDiv.style.width = '30px';
    this.buttonDiv.style.height = '18px';
    this.buttonDiv.style.position = 'absolute';
    this.buttonDiv.style.top = '0px';
    this.buttonDiv.style.right = '5px';
    this.buttonDiv.style.textAlign = 'center';
    this.buttonDiv.style.background = 'red';
    this.buttonDiv.style.border = '0px 1px 1px 1px solid #000';
    this.buttonDiv.innerHTML = 'x';
    this.buttonDiv.addEventListener('click', function(e) {
        document.body.removeChild(e.target.parentNode.parentNode);
    }, false);

    this.headerDiv.appendChild(this.buttonDiv);
    this.windowDiv.appendChild(this.headerDiv);
    document.body.appendChild(this.windowDiv);
}

// Initialize
var myWindow = new Window({
    width: 400,
    height: 200,
    title: 'My Window'
});
myWindow.testMethod();

这感觉不太“正确”。另一种方法可能是使用 render() 方法并使用它来分离 HTML 生成代码。 JS 对象内部包含多个嵌套的 HTML 对象,这看起来很尴尬。我应该通过innerHTML 传递嵌套标签吗?

所以我很好奇......这里最好的方法是什么?设计具有 DOM 代码(HTML 对象和样式)以及传统变量和方法的类的最佳方法是什么?有没有办法对这些 HTML 对象使用原型?您甚至可以想象在此示例中还有一个 WindowManager 类,它包含实例化的 Window 对象,帮助管理它们并创建新对象。而且它也可以有 HTML 表示形式。

上面的一些内容可以使用静态 CSS 来处理,并应用 ID/类来清理一些代码,但我们只能说定位和大小必须以编程方式完成(以处理调整大小、拖放等)。

我对 ExtJS、jQuery 等提供的框架级解决方案不感兴趣。我想知道本土代码的最佳实践是什么。事实上,我很想知道上述框架的工程师如何设计他们的 UI 类。

I am very familiar with JavaScript and OOP but am very unfamiliar with designing JS classes that are used for programming the UI (HTML). I have searched around a bit but have not come across any prevalent patterns.

Let's say I wanted to dynamically create panel-like objects (similar to Microsoft Windows panels). Each object needs a container, a header area that could include a text label, and a close button that has a click event handler. In addition to a DOM representation (HTML), the object would also have a JavaScript object representation (variables and methods). Here is one way I have tried:

//
// Window class
//
var Window = function(params) {
    this.testMethod = function() {
        console.log('test');  // just an example
    }

    this.windowDiv = document.createElement('div');
    this.windowDiv.style.width = params.width + 'px';
    this.windowDiv.style.height = params.height + 'px';
    this.windowDiv.style.position = 'absolute';
    this.windowDiv.style.top = '30px';
    this.windowDiv.style.left = '30px';
    this.windowDiv.style.border = '1px solid #000';

    this.headerDiv = document.createElement('div');
    this.headerDiv.style.width = '100%';
    this.headerDiv.style.height = '30px';
    this.headerDiv.style.background = '#bbb';
    this.headerDiv.style.borderBottom = '1px solid #000';
    this.headerDiv.innerHTML = params.title;

    this.buttonDiv = document.createElement('div');
    this.buttonDiv.style.width = '30px';
    this.buttonDiv.style.height = '18px';
    this.buttonDiv.style.position = 'absolute';
    this.buttonDiv.style.top = '0px';
    this.buttonDiv.style.right = '5px';
    this.buttonDiv.style.textAlign = 'center';
    this.buttonDiv.style.background = 'red';
    this.buttonDiv.style.border = '0px 1px 1px 1px solid #000';
    this.buttonDiv.innerHTML = 'x';
    this.buttonDiv.addEventListener('click', function(e) {
        document.body.removeChild(e.target.parentNode.parentNode);
    }, false);

    this.headerDiv.appendChild(this.buttonDiv);
    this.windowDiv.appendChild(this.headerDiv);
    document.body.appendChild(this.windowDiv);
}

// Initialize
var myWindow = new Window({
    width: 400,
    height: 200,
    title: 'My Window'
});
myWindow.testMethod();

This doesn't feel "right." Another approach might be to have a render() method and use it to separate out the HTML generation code. It seems awkward that the JS object contains multiple nested HTML objects inside of it. Should I just pass in the nested tags via innerHTML?

So I am curious... what is the best approach here? What is the best way to design classes that have DOM code (HTML objects and styling) and traditional variables and methods? Is there a way to use Prototypes for these HTML objects? You can even imagine in this example that there is also a WindowManager class that contains instantiated Window objects, helps manage them, and creates new ones. And it, too, could have an HTML representation.

Some of the above could be handled with static CSS and applying IDs/classes to clean up some of the code, but let's just say that positioning and size must be accomplished programmatically (to handle resizing, drag-drop, etc.).

I am not interested in framework-level solutions that could be provided by ExtJS, jQuery, etc. I want to know what the best practices are for home-grown code. In fact, I'd be interested in knowing how the engineers of said frameworks design their UI classes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

顾忌 2024-11-25 05:58:53

对于对象的 HTML 部分,您可以使用模板来定义组件的 HTML 结构,并在组件初始化时插入所需的任何数据。实现模板功能的方法有很多种,请看 underscore.js 的示例。

对于样式,我会将默认值放入样式表中。如果稍后需要通过 javascript 修改它们也没关系,即使它们是在 css 中定义的,那仍然可以工作。组件中应该包含的唯一信息是该组件触发的各种事件的默认行为。

您还可以考虑创建一个简单的原型链,用于将公共属性放入基“类”中(了解 javascript 没有真正的类),再次参考 underscore.js 以获取执行此操作的扩展函数的示例,以及其他实现可以用谷歌搜索。

最后,最重要的是您的代码易于使用和理解,并且性能相当好。您还可以返回并改进工作不太好的部分,或者将代码重新组织成模块。

For the HTML part of the object, you could use a template to define the HTML structure of the component, plugging in whatever data is necessary when the component is initialized. There are many ways to implement the template function, take a look at underscore.js for an example.

For the styles, I would put the default values in the stylesheet. It doesn't matter if they need to be modified later via javascript, that will still work even if they are defined in css. The only information that should be in the component is the default behavior of the various events that that component fires.

You could also look into creating a simple prototype chain for putting common properties inside base "classes" (understanding that javascript has no real classes), again refer to underscore.js for an example of the extend function that does this, among other implementations that can be googled.

In the end, all that matters is your code is easy to use and understand, and performs reasonably well. You can also go back and improve parts that don't work quite so well, or reorganize the code into modules.

梦言归人 2024-11-25 05:58:53

Backbone.js 非常适合您所述的要求:

http://documentcloud.github.com/backbone/

我将 html 存储在模板中,并将它们加载到控制器管理的视觉元素(为每个实例动态创建的 div)。这为我提供了可重用的 html 元素以及特定于每个实例的 UI 的方法和属性。用户界面。

Backbone.js is a good fit for your stated requirements:

http://documentcloud.github.com/backbone/

I store html inside Templates and load them to the visual element that the controller manages (a dynamically created div for each instance).. this gives me reusable html elements and methods and properties of the UI that are specific to each instance of the UI.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文