1

我是 JavaScript 的初学者,我正在编写一个简单的待办事项列表应用程序。它接受用户输入并将其添加为以checkbox.

问题是,代码变得越来越重复,我试图为重复最多的部分制作函数。但我觉得使用某种 DOM 本机函数有更好的方法来做到这一点。

这是我的代码(我正在写一条评论,我觉得有更好的选择):

window.onload = function(){
    submitBtn.addEventListener("click", function(){ 

         //Some code ...                

        var task = document.createElement("input"); 
        task.id = "task" + i;
        task.type = "checkbox"; 

        var taskLabel = document.createElement("label"); 
        taskLabel.htmlFor = "task" + i;
        taskLabel.appendChild(document.createTextNode(textBox.value));

         //This is from a function i've created to create buttons
        var deleteBtn = createButton("delete");
        var undoBtn = createButton("undo", "none");
        var divideBtn = createButton("divide");

        var taskContainer = document.createElement("p"); 

        //A LOT of appendChild is happening .. How can i minimize that using 
        //native DOM methods
        taskContainer.appendChild(task); 
        taskContainer.appendChild(taskLabel);
        taskContainer.appendChild(deleteBtn);
        taskContainer.appendChild(divideBtn);
        taskContainer.appendChild(undoBtn);

        taskPool.appendChild(taskContainer);        

         //the rest of the code ....



    }); 


}
4

2 回答 2

2

这就是大多数人使用 jQuery 和模板系统(如 Handlebars 或 Mustache)的原因。它实际上要快得多,更不用说实现更简洁,因此更易于维护,只需将完整的视图块插入 DOM,而不是手动创建单个 DOM 元素并逐个附加它们。

使用 jQuery 操作 DOM 的推荐方法是执行以下操作:

var taskName = 'task'+i,
    taskLabel = textBox.value,
    taskHtml =
        '<div>
            <input type="checkbox" name="'+taskName+'">
            <label for="'+taskNAme+'">'+taskLabel+'</label>
            <fieldset>
                <button id="btnDel'+i+'">Delete</button>
                <button id="btnDiv'+i+'">Divide</button>
                <button id="btnUndo'+i+'">Undo</button>
            </fieldset>
        </div>';
$(taskHtml).appendTo('#TaskPool');

一次性创建大型 DOM 结构innerHTML比手动创建和附加单个元素要快得多。

但是,这仍然需要混合 HTML 和 JS,这非常难看。这就是为什么现在开发人员选择模板的原因,它允许您执行以下操作:

<script id="task-template" type="text/x-handlebars-template">
    <div>
        <input type="checkbox" name="task{{i}}">
        <label for="task{{i}}">{{label}}</label>
        <fieldset>
            <button id="btnDel{{i}}">Delete</button>
            <button id="btnDiv{{i}}">Divide</button>
            <button id="btnUndo{{i}}">Undo</button>
        </fieldset>
    </div>
</script>

然后在您的点击处理程序中:

var source = $("#task-template").html(),
    template = Handlebars.compile(source),
    context = {
      i: i,
      label: textBox.value
    },
    html = template(context);
$('#TaskPool').append(html);

从那里,您可以更进一步,添加双向数据绑定,例如通过 Angular.js、Kockout.js 或 jsViews (+ jsRender)。然后你就有这样的东西:

<ol id="TasksList">
    <li ng-repeat="task in tasks | orderBy:orderProp">
        <input type="checkbox" name="{{task.name}}" ng:model="task.checked">
        <label for="{{task.name}}">{{task.label}}</label>
        <fieldset>
            <button ng-click="deleteTask(task.id)">Delete</button>
            <button ng-click="divideTask(task.id)">Divide</button>
            <button ng-click="undoTask(task.id)">Undo</button>
        </fieldset>
    </li>            
</ol>

在你的控制器中:

$scope.orderProp = 'id';
$scope.nextId = 0;
$scope.addTask = function(label) {
    var id = $scope.nextId++,
        task = {
            id: id,
            label: label,
            name: 'task'+id,
            checked: false
        };
    $scope.tasks.push(task);
};
$scope.deleteTask = function(id) { ... };
$scope.divideTask = function(id) { ... };
$scope.undoTask = function(id) { ... };
于 2012-07-30T03:07:43.817 回答
1

如果你想尽可能地最小化你的代码,那么使用像 jquery 这样的库将是你最好的选择之一。

但是,如果在这种情况下您更愿意坚持使用“纯”javascript,则可以通过向 DOM 的 Node 对象添加一个类似于以下的方法来避免所有附加:

/* is Node.prototype.multiAppend already defined? */
if( typeof Node.prototype.multiAppend !== "function" ) {
    Node.prototype.multiAppend = (function() {
        /*get the Array.prototype.slice method to use on the returned function*/
        var slice = [].slice;

        /*the function multiAppend comes to be*/
        return function() {
            var i = 0,
                max = arguments.length;

            for (; i < max; i++) {
                this.appendChild(arguments[i]);
            }

            /*allow chainability*/
            return this;
        };
    })();
}

这将允许您执行以下操作:

var item = document.getElementsByClassName('item')[0],

    /*create elements*/
    h1 = document.createElement("h1"),
    div = document.createElement("div"),
    p = document.createElement("p");

    /*append them to item with just one line*/
    item.multiAppend(h1, div, p)​​​;​​​​​

看看这里的演示:http: //jsfiddle.net/8mjBR/2/ *

于 2012-07-29T21:59:46.877 回答