如何在Javascript中实现独立组件?

时间:2015-09-22 14:57:37

标签: javascript components modularity

我已经实现了简单的待办事项列表http://jsfiddle.net/tw9p9sw3/,可能添加/删除待办事项。

    (function (todoApp) {
    'use strict';

    todoApp.todoItemValue = '';

    function _appendListNode() {
        var listNode = document.createElement('li');
        listNode.className = 'list-group-item';
        listNode.appendChild(document.createTextNode(todoApp.todoItemValue));
        listNode.appendChild(_createRemoveItemButton());
        todoList.appendChild(listNode);
    }

    function _createRemoveItemButton() {
        var removeButtonNode = document.createElement('a'),
            removeButtonLabel = 'Remove';

        removeButtonNode.className = 'badge';
        removeButtonNode.appendChild(document.createTextNode(removeButtonLabel));

        return removeButtonNode;
    }

    function _addItem() {
        todoApp.todoItemValue = document.getElementById('todoInput').value;
        _appendListNode();
        document.getElementById('todoInput').value = '';
    }

    function _removeItem() {
        var nodeToRemove = this.parentNode;
        this.parentNode.parentNode.removeChild(nodeToRemove);
    }

    function _addEventHandlers() {
        document.getElementById('todoListForm').addEventListener('submit', function (event) {
            event.preventDefault();
            _addItem();
        });

        /*
         * Used delegated event cause todo list is not static,
         * so we don't need to add events for remove buttons each time after DOM of todo list have changed
         */
        document.getElementById('todoList').addEventListener('click', function (event) {
            if (event.target && event.target.nodeName === 'A') {
                event.preventDefault();
                _removeItem.call(event.target);
            }
        });
    }

    todoApp.init = function () {
        _addEventHandlers();
    };

}(window.todoApp = window.todoApp || {}));

//////////////////////////////////////////////////////////
// INITIALIZATION
//////////////////////////////////////////////////////////
document.onload = todoApp.init();

问题是如何将此待办事项列表重新制作为独立组件,例如我可以在同一页面上注入/实例化两次,并且todo列表实例之间应该没有冲突。

1 个答案:

答案 0 :(得分:1)

基本上你需要创建TodoList类,所以你可以创建这个类的实例,就像在使用OO编程的coments中所建议的那样。

这是代码:

var TodoListComponent = (function () {
    'use strict';

    var todoListTemplate =  '<div>' +
        '<div class="todo-list">' + 
        '<div class="form-container">' +
        '<form role="form" class="todoListForm">' + 
            '<div class="form-group">' +
                '<label for="todoInput">Add todo item</label>' +
                '<input type="text" class="form-control todoInput" required>' +
            '</div>' +
            '<button type="submit" class="btn btn-success">Submit</button>' +
        '</form>' +
    '</div>' +
    '<div class="list-container">' +
        '<ul class="list-group todoList">' + 
            '<li class="list-group-item list-group-item-success">Todo list</li>' +
       '</ul>' +
   '</div>' +
   '</div>' +
   '</div>';

    function TodoList() {

        this.initialize = function() {
            this.$el = $(todoListTemplate);
            this.todoItemValue = '';
            this._initEvents();
        }

        this._initEvents = function() {
            var self = this;

            this.$el.find('.todoListForm').on('submit', function (event) {
                event.preventDefault();
                self._addItem();
            });

            /*
             * Used delegated event cause todo list is not static,
             * so we don't need to add events for remove buttons each time after DOM of todo list have changed
             */
            this.$el.find('.todoList').on('click', function (event) {
                if (event.target && event.target.nodeName === 'A') {
                    event.preventDefault();
                    self._removeItem.call(event.target);
                }
            });
        }

        this._appendListNode = function () {
            var listNode = $('<li>');
            listNode.addClass('list-group-item');
            listNode.text(this.todoItemValue);
            listNode.append(this._createRemoveItemButton());
           this.$el.find('.todoList').append(listNode);
        }

        this._createRemoveItemButton = function () {
            var removeButtonNode = $('<a>'),
                removeButtonLabel = 'Remove';

            removeButtonNode.addClass('badge');
            removeButtonNode.text(removeButtonLabel);

            return removeButtonNode;
        }

        this._addItem = function() {
            var input = this.$el.find('.todoInput');
            this.todoItemValue = input.val();
            this._appendListNode();
            input.val('');
        }

        this._removeItem = function() {
            var nodeToRemove = this.parentNode;
            this.parentNode.parentNode.removeChild(nodeToRemove);
        }

         this.render = function() {
             return this;
         }

        this.initialize();
    }

    return TodoList;
}());

//////////////////////////////////////////////////////////
// INITIALIZATION
//////////////////////////////////////////////////////////

var todoList1 = new TodoListComponent();
var todoList2 = new TodoListComponent();

$('body').append(todoList1.render().$el);
$('body').append(todoList2.render().$el);

并且jsfiddle链接:http://jsfiddle.net/tw9p9sw3/10/

这样可行,但是如果你想使用数据,在某个地方发送物品或者其他什么,那么你可能会通过糟糕而混乱的DOM来获取它。

尝试使用Backbone,其中DOM仅用于表示,数据由Javascript保存。

以下是示例:

http://backbonejs.org/docs/todos.html