1

私はJavaScriptの初心者で、簡単なTo-Doリストアプリケーションを作成しています。これはユーザー入力を受け入れ、それを。の形式でタスクとして追加します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要素を手動で作成して1つずつ追加するのではなく、完全なビューブロックを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');

1回の実行で大きな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などのライブラリを使用するのが最善の選択肢の1つです。

ただし、この場合、「純粋な」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 に答える