如何遍历数组/有关单击事件目标的问题

时间:2019-06-03 09:32:13

标签: javascript arrays

我正在添加到收藏夹功能。如果我单击一个图标,该图标旁边的品种将添加到点赞数组。我做了renderLikes函数,使数组出现在屏幕上。但是,只有一个品种出现可能是因为elements.favorite.innerHTML =''部分。如果我不写该部分,则每次单击图标时,整个数组都会继续添加到DOM树中。我有什么办法可以渲染数组中的每个项目,例如

item

item2

...?

另一个问题,如果我单击图标有时会向数组添加一个空元素。如何预防此问题?

<!DOCTYPE html>
<html lang="en">
<head>
    <style>
        ul {
            list-style: none;
            line-height: 1.6;
        }
    .icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  stroke-width: 0;
  stroke: currentColor;
  fill: currentColor;
  vertical-align: middle;
  cursor: pointer;
  transition: transform .3s;
  transform: scale(0.8);
}
.icon:hover {
    transform: scale(1.6) rotate(-15deg);
}
.icon-fill {
    fill: red;
}
    </style>
    <title>Like Button Practice</title>
</head>

<body>
<ul class="list"></ul>

<h2>My Favorite Dogs</h2>
<div class="favorite">

</div>
    <script>

const data = [
    { 
        "breed": "Beagle",
        "characteristics": "playful" 
    },
    {
        "breed": "Golden Retriever", 
        "characteristics": "calm" 
    },
    {
        "breed": "Corgi", 
        "characteristics": "bright" 
    },
    {
        "breed": "Goldendoodle", 
        "characteristics": "gentle" 
    },
    {
        "breed": "Labrador Retriever", 
        "characteristics": "loyal" 
    },
]

const elements = {
    "icon": document.querySelectorAll('svg'),
    "dom": document.querySelector('.list'),
    "favorite": document.querySelector('.favorite')
}

const likes = [];

// Render method
function test() {
    data.map(item => {
        renderList(item.breed);        
        return item.breed;
    })
};
test();


function renderList(dog) {
    const markup = `
    <li id="${dog}">
        <svg class="icon icon-heart-outlined"><use xlink:href="icon/sprite.svg#icon-heart-outlined"></use></svg>  
        ${dog}
    </li>
    `;
    elements.dom.insertAdjacentHTML('beforeend', markup);    
}


function renderLikes(item) {
    const markup = `
    <p>${item}</p>
    `;
    elements.favorite.innerHTML = '';
    elements.favorite.insertAdjacentHTML('beforeend', markup);    
}


elements.dom.addEventListener('click', e => {


        const id = e.target.parentNode.id;

   if (e.target.matches('.icon, .icon *')) {

    // If (Beagle, Golden Retriever... does not exist in likes array, it returns -1)
    const index = likes.indexOf(e.target.parentNode.id);    

       if (index === -1) {

            likes.push(id);
            console.log(likes);

            likes.forEach(function( value ) {
            console.log( value );
            renderLikes(value);
});
        } else {
            likes.splice(index, 1);
        }
    }
});
    </script>
</body>
</html>

1 个答案:

答案 0 :(得分:1)

是的,innerHTML =''正在删除整个内容。

无论如何,您都应该使用数据并进行显示,请尽量不要将数据耦合到视图上。

我会解释...

您正在这样做:

  • 点击一个元素
  • 将其添加到数组
  • 绘制新元素所属的位置

这样做,您必须一次管理两种不同的逻辑,即渲染逻辑(在某物旁边绘画)和数据逻辑本身(在列表中添加或删除项目)。这导致不一致。 您应该管理数据,渲染逻辑应该显示数据。

我会这样做的。

  • 点击一个元素
  • 将其添加到列表中
  • 绘制列表中的所有元素

通过这样做,您始终可以确保渲染与正在使用的模型一致。 启用后,您可以进行性能调整,例如虚拟dom,差异渲染等。但是一致性是最重要的。

我的代码如下:

const $likelist = document.querySelector('.likelist');
const likeTemplate = i => `<p>Whatever ... ${i} blah blah </p>`;
const renderLikes = () => $likelist.innerHTML = likes.map(i => likeTemplate(i)).join();
const addToLikelist = (el) => {
  // Validate the item is valid and is not in the list yet
  likes.push(el);
  renderLikes();
}