我应该如何实现面向对象模式的交互式web应用程序(与jQuery的助手)

How should I implement OOP patterns to interactive web applications (with the aide of jQuery)?

本文关键字:应用程序 web jQuery 交互式 模式 何实现 实现 面向对象 我应该      更新时间:2023-09-26

有时,使用jQuery会导致您滥用它的功能(至少对我来说是这样,因为它的选择器匹配功能)。到处都有事件处理程序。这里到处都是效用函数。代码一致性几乎不存在。我想通过实现面向对象模式来缓解这个问题,但由于我有c++和python背景,在javascript中实现它有点让我感到奇怪。

下面的代码使用OOP模式,但我不完全确定我的实现是否是好的实践。我怀疑我的实现的原因是因为我上一个stackoverflow问题中的第三条评论。我知道这只是我代码中他注释的一个特定细节,但这也让我想知道我在代码中实现的其他模式。

如果你能指出我的模式中的缺陷和陷阱和/或你有任何建议,我将非常感激。提前感谢。

(这段代码是我正在开发的东西的简化,但思想是相似的)

生活例子

$(function(){
    var stream = new Stream();
});

/*          Stream Class
------------------------------------------*/
function Stream(){
    // Disables multiple Stream objects
    if (this.singleton)
        return
    else
        this.__proto__.singleton = true;

    this.elements = jQueryMapping(this.selectors) // Converts a map of selectors to a map of jQuery objects
    this.initEvents();
}
Stream.prototype.singleton = false;
Stream.prototype.selectors = {
    stream : '#stream',
    post_content : '#post-content',
    add_post: '#add-post',
    // ... more action selectors
}
Stream.prototype.initEvents = function(){
    this.elements.add_post.click(this, this.addPost);
    // ... more action event-listeners
}
Stream.prototype.addPost = function(e){
    var self = e.data;
    var post_content = self.elements.post_content.val();
    if (post_content)
        self.elements.stream.append(new Post(post_content));
}

/*          Post Class
------------------------------------------*/
function Post(post_content){
    this.$element = $('<li>')
                        .text(post_content)
                        .append('<button class="delete-post">Delete</button>');
    this.elements = jQueryMapping(this.selectors, this.$element);
    this.initEvents();
    return this.$element;
}
Post.prototype.selectors = {
    delete_post: 'button.delete-post',
    // ... more action selectors
}
Post.prototype.initEvents = function(){
    this.elements.delete_post.click(this.deletePost);
    // ... more action event-listeners
}
Post.prototype.deletePost = function(){
    $(this).parent().slideUp();
}

/*          Utils
------------------------------------------*/
function jQueryMapping(map, context){
    // Converts a map of selectors to a map of jQuery objects
    var $map = {};
    $.each(map, function(key, value){ 
            $map[key] = (context) ? $(value, context) : $(value);
    });
    return $map;
}

我认为你的代码设计过度了。我对它进行了重构,并简化了它,如图所示。如果你真的想要一个沉重的OOP设置,我建议你使用客户端MVC (Backbone, knockout等)结构来正确地完成它,或者保持它的轻量。

我将继续对您的代码进行一般反馈。

/*          Stream Class
------------------------------------------*/
function Stream(){
    // Disables multiple Stream objects
    if (this.singleton)
        return
    else
        this.__proto__.singleton = true;

    this.elements = jQueryMapping(this.selectors) // Converts a map of selectors to a map of jQuery objects
    this.initEvents();
}

没有理由像这样使用单例。使用.__proto__

也是非常不好的

我推荐这样的样式。

var Stream = (function() {
    var Stream = function() { ... };
    // prototype stuff
    var stream = new Stream();
    return function() {
         return stream;
    };
})());

在原型上存储这样的数据散列是不必要的。

Stream.prototype.selectors = {
    stream : '#stream',
    post_content : '#post-content',
    add_post: '#add-post',
    // ... more action selectors
}

你可以把它作为默认的哈希值。

(function() {
    var defaults = {
        stream : '#stream',
        post_content : '#post-content',
        add_post: '#add-post',
        // ... more action selectors
    }
    function Stream() {
         ...
         this.elements = jQueryMapping(defaults);
    }
}());

你的效用函数可以稍微优化一下。

$map[key] = (context) ? $(value, context) : $(value);

可以重写为

$map[key] = $(value, context)

因为如果context是未定义的,你只是传递一个未定义的参数,这与不传递参数相同。

这篇文章的标题是"初学者",但是我发现这一节是关于设计模式的,这一节是关于使用jQuery设计模式的。