Обертывание элемента DOM внутри объекта JavaScript - PullRequest
7 голосов
/ 20 января 2011

Я заметил общий шаблон в JavaScript, который я писал, и мне было интересно, существует ли уже шаблон, который определяет нечто подобное в качестве наилучшей практики?По сути, это как получить элемент DOM и обернуть его внутри / связать с объектом JavaScript.Возьмите этот пример, где вам нужен фильтр в вашем веб-приложении.Ваша страница выглядит следующим образом:

<html>
<head></head>
<body>
    <div id="filter"></div>
</body>
</html>

Затем вы оберните элемент следующим образом:

var myFilter = new Filter({
    elem: document.getElementById('filter'),
    prop: 'stacks-test',
    someCallback: function() {
        // specify a callback
    }
});

И JavaScript (где spec - это объект, переданный конструктору):

var Filter = function(spec) {
    this.elem = spec.elem;
    this.prop = spec.prop;
    this.callback = spec.someCallback;
    this.bindEvents();
};

Filter.prototype.bindEvents = function() {
    var self = this;
    $(this.elem).click(function(e) {
        self.updateFeed();
    };
};

Filter.prototype.updateFeed = function() {
    this.prop; // 'stacks-test'
    this.callback();
    // ...
    // code to interact with other JavaScript objects
    // who in turn, update the document
};

Как называется такой подход, и каковы лучшие практики и предостережения?

Ответы [ 2 ]

2 голосов
/ 23 января 2011

Возможно, вас заинтересует библиотека виджетов Dojo, Dijit - если я правильно понимаю ваш вопрос, она, по сути, делает то, что вы просите, и многое другое.

В Dijit виджет по существу инкапсулирует узел DOM, его содержимое, любой JavaScript, который определяет его поведение, и (импортируется отдельно) CSS для стилизации его внешнего вида.

Виджеты имеют свой собственный жизненный цикл, реестр и события (включая многие, которые просто отображаются на события DOM на узле в виджете, например, myWidget.onClick может эффективно вызывать myWidget.domNode.onclick).

Виджеты могут (но не обязаны) иметь свое начальное содержимое, определенное в отдельном файле шаблона HTML, с помощью которого также можно привязывать события на узлах в шаблоне к методам виджета, а также устанавливать свойства виджета. которые ссылаются на определенные узлы в шаблоне.

Я едва царапаю поверхность здесь. Если вы хотите узнать больше об этом, вы можете начать со следующих справочных страниц:

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

1 голос
/ 20 января 2011

Продолжая мой комментарий к этому вопросу, jQuery является потенциальным инструментом для работы, поскольку он уже обеспечивает некоторые основы того, что вы ищете. Тем не менее, сказав это, он вносит свои сложности, и, кроме того, не все «способы jQuery» равны. Я предложу один из способов использования jQuery в качестве вашей «объектной модели», но он может соответствовать или не соответствовать вашим потребностям.


Сначала обо всем. Философия jQuery заключается в том, что вы начинаете все, сначала выбирая элемент, используя $() или, что то же самое, jQuery(). Все операции концептуально начинаются с этого. Это немного другой способ мышления по сравнению с созданием объекта, который оборачивает элемент и хранит ссылку на эту обертку, но по сути это то, что jQuery делает для вас. Вызов $('#some-id') захватывает элемент с идентификатором «some-id» и помещает его в объект jQuery.


В одну сторону: Написать плагины «Filter».

Замените ваш конструктор методом initFilter() jQuery. Вы можете сделать это, изменив прототип jQuery и используя объект jQuery в качестве оболочки. На прототип jQuery ссылается jQuery.fn, поэтому:

jQuery.fn.initFilter = function (prop, callback) {
    // Save prop and callback
    this.data('filter-prop', prop);
    this.data('filter-callback', callback);

    // Bind events (makes sense to do this during init)
    this.click(function () {
        $(this).updateFeed();
    });
};

Затем сделайте аналогичную вещь для updateFeed():

jQuery.fn.updateFeed = function () {
    this.data('filter-prop');
    this.data('filter-callback')();
});

И используйте это так:

$('#filter').initFilter(prop, callback);

Обратите внимание, что updateFeed может быть просто встроен в обработчик кликов, чтобы предотвратить ненужное загрязнение пространства имен jQuery. Тем не менее, одно из преимуществ использования jQuery, подобного этому, заключается в том, что вам не нужно сохранять ссылку на объект, если вам нужно позже вызвать некоторую функцию для него, поскольку jQuery связывает все ссылки с реальными элементами. Если вы хотите вызвать updateFeed программно, тогда:

$('#filter').updateFeed();

будет затем вызываться для правильного объекта.


Некоторые вещи для рассмотрения

Есть, конечно, недостатки этого метода. Во-первых, все свойства, которые мы сохранили для элемента с помощью .data(), являются общими для всех функций jQuery, которые действуют на этот элемент. Я попытался облегчить это, добавив префикс имени свойства к «filter-», но в зависимости от сложности ваших объектов, это может не подойти.

Кроме того, этот точный метод может не подходить для объектов, требующих большого количества манипуляций (например, объектов со многими функциями), поскольку все эти функции становятся общими для всех объектов jQuery. Есть способы инкапсулировать все это, но я не буду здесь вдаваться, но jQuery-ui делает это с их виджетами, и я экспериментирую с еще одной альтернативой в библиотеке, которую я создаю.

Однако, немного отступив, единственная причина, по которой я предложил использовать jQuery, заключается в том, что ваш объект Filter сильно привязан к DOM. Он связывает события с DOM, он модифицирует DOM на основе взаимодействия с пользователем, в основном он, кажется, живет в DOM, поэтому используйте что-то на основе DOM, то есть jQuery.

...