6

伙计们!今天我创建了这个脚本,它具有以下功能:

  • 将新项目添加到数组
  • 列出数组中的所有项目
  • 从数组中删除一个项目

有两个功能:

  • addToFood() - 将输入值添加到数组并更新 div 的 innerHTML
  • removeRecord(i) - 从数组中删除一条记录并更新 div 的 innerHTML

该代码包括 3 个 for 循环,您可以在 - http://jsfiddle.net/menian/3b4qp/1/看到它

我的主人告诉我,这 3 个 for 循环使解决方案变得繁重。有没有更好的方法来做同样的事情?减少循环并尝试使用拼接会更好吗?提前致谢。

HTML

<!-- we add to our foodList from the value of the following input -->    
<input type="text" value="food" id="addFood" />

<!-- we call addToFood(); through the following button  -->    
<input type="submit" value="Add more to food" onClick="addToFood();">

<!-- The list of food is displayed in the following div -->    
<div id="foods"></div>

JavaScript

var foodList = [];

function addToFood () {
    var addFood = document.getElementById('addFood').value;
    foodList.push(addFood);

    for (i = 0; i < foodList.length; i++)   {
        var newFood = "<a href='#' onClick='removeRecord(" + i + ");'>X</a> " + foodList[i] + " <br>";
    };
    document.getElementById('foods').innerHTML += newFood;
}


function removeRecord (i) {

    // define variable j with equal to the number we got from removeRecord
    var j = i;

    // define and create a new temporary array
    var tempList = [];

    // empty newFood
    // at the end of the function we "refill" it with the new content
    var newFood = "";
    for (var i = 0; i < foodList.length; i++) {
        if(i != j) {

    // we add all records except the one == to j to the new array
    // the record eual to j is the one we've clicked on X to remove
            tempList.push(foodList[i]);
        } 
    };

    // make redefine foodList by making it equal to the tempList array
    // it should be smaller with one record
    foodList = tempList;

    // re-display the records from foodList the same way we did it in addToFood()
    for (var i = 0; i < foodList.length; i++) {
        newFood += "<a href='#' onClick='removeRecord(" + i + ");'>X</a> " + foodList[i] + " <br>";
    };
    document.getElementById('foods').innerHTML = newFood;
}
4

4 回答 4

5

你应该使用array.splice(position,nbItems)

function removeRecord (i) {
    foodList.splice(i, 1); // remove element at position i
    var newFood = "";
    for (var i = 0; i < foodList.length; i++) {
        newFood += "<a href='#' onClick='removeRecord(" + i + ");'>X</a> "
            + foodList[i] + " <br>";
    };
    document.getElementById('foods').innerHTML = newFood;
}

http://jsfiddle.net/3b4qp/5/

现在使用 JQuery:

$(function(){
    $(document).on('click','input[type=submit]',function(){
        $('#foods')
           .append('<div><a href="#" class="item">X</a> ' 
                + $('#addFood').val() + '</div>');
    });

    $(document).on('click','.item',function(){
        $(this).parent().remove();
    });
});

http://jsfiddle.net/jfWa3/

于 2013-02-11T15:54:04.267 回答
3

你的问题不是数组,你的问题是这段代码:

node.innerHTML += newFood;

这段代码非常非常非常慢。它将遍历所有现有的 DOM 节点,从它们创建字符串,将这些字符串连接成一个长字符串,附加一个新字符串,将结果解析为新的 DOM 节点树。

我建议使用像 jQuery 这样的框架,它具有将 HTML 片段附加到现有 DOM 节点的方法:

var parent = $('#foods');
...
for (var i = 0; i < foodList.length; i++) {
    parent.append( "<a href='#' onClick='removeReco..." );

这将只解析 HTML 片段一次。

如果您确实必须手动执行此操作,则将所有 HTML 收集到一个本地字符串变量中(如 JohnJohnGa 在他的回答中所建议的那样),然后分配innerHTML一次。

于 2013-02-11T15:59:05.000 回答
2

这里有一些技巧,至少可以让你的代码更便携(不知道它是否会更好的性能,但应该是,因为 DOM 操作更便宜)

尖端

  1. 首先将您的事件句柄与 HTML 分开
  2. 将“新食物”作为函数参数传递
  3. 使用 ID 将数组元素绑定到 DOM
  4. 而不是在发生变化时重新渲染所有内容(使用列表中的 innerHTML),只需更改相关位

好处:

  1. 您实际上只循环一次(从数组中删除元素时)。
  2. 每次发生更改时,您都不会重新渲染列表,只需单击元素
  3. 额外的好处:它更便携。
  4. 应该更快

示例代码:

小提琴

HTML

<div id="eventBinder">
    <!-- we add to our foodList from the value of the following input -->
    <input id="addFood" type="text" value="food" />
    <!-- we call addToFood(); through the following button -->
    <button id="addFoodBtn" value="Add more to food">Add Food</button>
    <!-- The list of food is displayed in the following div
    -->
    <div id="foods"></div>
</div>

JS

// FoodList Class
var FoodList = function (selectorID) {
    return {
        foodArray: [],
        listEl: document.getElementById(selectorID),
        idCnt: 0,
        add: function (newFood) {
            var id = 'myfood-' + this.idCnt;
            this.foodArray.push({
                id: id,
                food: newFood
            });
            var foodDom = document.createElement('div'),
                foodText = document.createTextNode(newFood);
            foodDom.setAttribute('id', id);
            foodDom.setAttribute('class', 'aFood');
            foodDom.appendChild(foodText);
            this.listEl.appendChild(foodDom);
            ++this.idCnt;
        },
        remove: function (foodID) {
            for (var f in this.foodArray) {
                if (this.foodArray[f].id === foodID) {
                    delete this.foodArray[f];
                    var delFood = document.getElementById(foodID);
                    this.listEl.removeChild(delFood);
                }
            }
        }
    };
};

//Actual app
window.myFoodList = new FoodList('foods');

document.getElementById('eventBinder').addEventListener('click', function (e) {
    if (e.target.id === 'addFoodBtn') {
        var food = document.getElementById('addFood').value;
        window.myFoodList.add(food);
    } else if (e.target.className === 'aFood') {
        window.myFoodList.remove(e.target.id);
    }
}, false);
于 2013-02-11T16:38:35.857 回答
1

这是另一个建议:

function remove(arr, index) {
  if (index >= arr.lenght) { return undefined; }
  if (index == 0) {
    arr.shift();
    return arr;
  }

  if (index == arr.length - 1) {
    arr.pop();
    return arr;
  }
  var newarray = arr.splice(0, index);
  return newarray.concat(arr.splice(1,arr.length))
}
于 2013-02-11T15:58:57.160 回答