Как мне реализовать шаблоны ООП для интерактивных веб-приложений (с помощью jQuery)? - PullRequest
3 голосов
/ 07 мая 2011

Иногда использование jQuery побуждает вас злоупотреблять его мощью (по крайней мере, для меня из-за его способности выбора селектора).Обработчики событий здесь и там.Утилита функционирует здесь и везде.Согласованность кода может казаться почти несуществующей.Я хочу решить эту проблему, внедрив шаблоны ООП, но, поскольку у меня есть C ++ и фон Python, его реализация в javascript немного утомляет меня.

В приведенном ниже коде используются шаблоны ООП, но я неполностью уверен, что мои реализации - хорошие практики.Причина, по которой я сомневаюсь в моих реализациях, заключается в том, что 3-й комментарий в мой последний вопрос о переполнении стека .Я знаю, что он прокомментировал только одну деталь в моем коде, но это также заставляет меня задуматься о других шаблонах, которые я реализую в своем коде.

Буду очень признателен, если вы укажете на недостатки и подводные камни в моих моделях и / или если у вас есть какие-либо предложения.Заранее большое спасибо.

(этот код является упрощением того, что я разрабатываю, но идея похожа)

Live Example

$(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;
}

Ответы [ 2 ]

3 голосов
/ 07 мая 2011

Я полагаю, ваш код перегружен.Я пересмотрел и упростил его, как можно увидеть здесь .Если вы действительно хотите интенсивную настройку ООП, я рекомендую использовать клиентскую конструкцию 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 не определено, вы просто передаете неопределенный параметр, который аналогичен передаче без параметра.

1 голос
/ 07 мая 2011

В заголовке написано «для начинающих», но я нашел этот раздел о шаблонах проектирования и этот раздел о шаблонах проектирования с использованием jQuery.

...