简体   繁体   English

一个很好的JavaScript来添加/删除数组中的项目?

[英]A good JavaScript to add/remove items from/to array?

folks! 乡亲! Today I created this script that has the following functionality: 今天我创建了这个具有以下功能的脚本:

  • add new items to array 将新项添加到数组
  • list all items from the array 列出数组中的所有项目
  • remove an item from the array 从数组中删除一个项目

There are two functions: 有两个功能:

  • addToFood() - adds the value of input to the array and updates innerHTML of div addToFood() - 将输入值添加到数组并更新div的innerHTML
  • removeRecord(i) - remove a record from the array and updates innerHTML of div removeRecord(i) - 从数组中删除一条记录并更新div的innerHTML

The code includes 3 for loops and you can see it at - http://jsfiddle.net/menian/3b4qp/1/ 代码包括3个for循环,你可以在http://jsfiddle.net/menian/3b4qp/1/看到它

My Master told me that those 3 for loops make the solution way to heavy. 我的主人告诉我,那3个for循环使解决方案变得沉重。 Is there a better way to do the same thing? 有没有更好的方法来做同样的事情? Is it better to decrease the loops and try to use splice? 减少循环并尝试使用拼接更好吗? Thanks in advance. 提前致谢。

HTML 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 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;
}

You should use array.splice(position,nbItems) 你应该使用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/ http://jsfiddle.net/3b4qp/5/

Now using JQuery: 现在使用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/ http://jsfiddle.net/jfWa3/

Your problem isn't the arrays, your problem is this code: 你的问题不是数组,你的问题是这段代码:

node.innerHTML += newFood;

This code is very, very, very slow. 这段代码非常非常非常慢。 It will traverse all exising DOM nodes, create strings from them, join those strings into one long string, append a new string, parse the result to a new tree of DOM nodes. 它将遍历所有正在进行的DOM节点,从它们创建字符串,将这些字符串连接成一个长字符串,附加一个新字符串,将结果解析为一个新的DOM节点树。

I suggest to use a framework like jQuery which has methods to append HTML fragments to existing DOM nodes: 我建议使用像jQuery这样的框架,它具有将HTML片段附加到现有DOM节点的方法:

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

That will parse the HTML fragments only once. 这将只解析HTML片段一次。

If you really must do it manually, then collect all the HTML in a local string variable (as suggested by JohnJohnGa in his answer) and then assign innerHTML once. 如果你真的必须手动完成,那么收集本地字符串变量中的所有HTML(如JohnJohnGa在他的回答中所建议的那样)然后分配innerHTML一次。

Here's some tips to, at least, make your code more portable (dunno if it will be better performance wise, but should be, since DOM Manipulation is less expensive) 这里有一些提示,至少可以使你的代码更具可移植性(如果性能更好,那就不知道了,但应该是,因为DOM操作更便宜)

Tips 提示

  1. First separate your event handle from the HTML 首先将您的事件句柄与HTML分开
  2. Pass the "new food" as a function paramater 将“新食物”作为功能参数传递
  3. Tie the array elements to the DOM using the ID 使用ID将数组元素绑定到DOM
  4. Instead of rerendering everything when something changes (using innerHTML in the list), just change the relevant bit 不是在某些事情发生变化时重新渲染所有内容(使用列表中的innerHTML),只需更改相关位即可

Benefits: 优点:

  1. You actually only loop once (when removing elements from the array). 实际上你只循环一次(当从数组中删除元素时)。
  2. You don't re-render the list everytime something changes, just the element clicked 每次更改时,您都不会重新呈现列表,只需单击该元素
  3. Added bonus: It's more portable. 额外奖励:它更便携。
  4. Should be faster 应该更快

Example code: 示例代码:

FIDDLE 小提琴

HTML 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 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);

Here is another sugestion: 这是另一个消化:

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))
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM