更改属性后呈现数组项

时间:2019-01-15 16:52:39

标签: javascript arrays rendering

在对数组中的元素进行更改之后,我无法重新渲染数组中的项目。无论我是通过推入添加还是通过拼接来删除,当数组再次在页面上呈现时,就像有更多项正在添加到数组中一样。因此,如果我将其推入阵列,则会添加该项目,但随后会将旧项目复制到阵列中。当我删除项目时,也会发生类似的情况。看起来该项目已被删除,但是数组中的元素显示在页面上,然后将它们复制并且被拼接的项目消失了。

我正在尝试避免使用location.reload('/ edit.html')刷新页面。有点作弊。看来可行,但是我正在尝试使用renderIngredients函数刷新页面。当我检查项目时,toggleIngredient函数还会复制项目列表。

import { initializeEditPage, generateLastEdited } from './views'
import { updateRecipe, removeRecipe, saveRecipes, getRecipes, createIngredient } from './recipes'

const titleElement = document.querySelector('#recipe-title')
const bodyElement = document.querySelector('#recipe-body')
const removeElement = document.querySelector('#remove-recipe')
const addElement = document.querySelector('#add-recipe')
const dateElement = document.querySelector('#last-updated')
const addIngredient = document.querySelector('#new-ingredient')
const recipeStatus = document.querySelector('#recipe-status')

const recipeId = location.hash.substring(1)
const recipeOnPage = getRecipes().find((item) => item.id === recipeId)

titleElement.addEventListener('input', (e) => {
    const recipe = updateRecipe(recipeId, {
        title: e.target.value
    })
    dateElement.textContent = generateLastEdited(recipe.updatedAt)
})

bodyElement.addEventListener('input', (e) => {
    const recipe = updateRecipe(recipeId, {
        body: e.target.value
    })
    dateElement.textContent = generateLastEdited(recipe.updatedAt)
})

addElement.addEventListener('click', () => {
    saveRecipes()
    location.assign('/index.html')
})

removeElement.addEventListener('click', () => {
    removeRecipe(recipeId)
    location.assign('/index.html')
})

addIngredient.addEventListener('submit', (e) => {
    const text = e.target.elements.text.value.trim()
    e.preventDefault()

    if (text.length > 0) {
        createIngredient(recipeId, text)
        e.target.elements.text.value = ''
    }
    renderIngredients(recipeId)
    saveRecipes()
    //location.reload('/edit.html')
})

const removeIngredient = (text) => {
    const ingredientIndex = recipeOnPage.ingredients.findIndex((ingredient)=> ingredient.text === text)
    if (ingredientIndex > -1) {
        recipeOnPage.ingredients.splice(ingredientIndex, 1)
    }
    saveRecipes()
    renderIngredients(recipeId)
    //location.reload('/edit.html')
}

const toggleIngredient = (text) => {
    const ingredient = recipeOnPage.ingredients.find((ingredient) => ingredient.text === text)
    if (ingredient.included) {
        ingredient.included = false
    } else {
        ingredient.included = true
    }
    //location.reload('/edit.html')
}

const ingredientSummary = (recipe) => {
    let message
    const allUnchecked = recipeOnPage.ingredients.every((ingredient) => ingredient.included === false)
    const allChecked = recipeOnPage.ingredients.every((ingredient) => ingredient.included === true)

    if (allUnchecked) {
        message = `none`
    } else if (allChecked) {
        message = `all`
    } else {
        message = `some`
    }
    return `You have ${message} ingredients for this recipe`
}

const generateIngredientDOM = (ingredient) => {
    const ingredientEl = document.createElement('label')
    const containerEl = document.createElement('div')
    const checkbox = document.createElement('input')
    const ingredientText = document.createElement('span')
    const removeButton = document.createElement('button')
    recipeStatus.textContent = ingredientSummary(recipeOnPage)

    // Setup ingredient container
    ingredientEl.classList.add('list-item')
    containerEl.classList.add('list-item__container')
    ingredientEl.appendChild(containerEl)

    // Setup ingredient checkbox
    checkbox.setAttribute('type', 'checkbox')
    checkbox.checked = ingredient.included
    containerEl.appendChild(checkbox)
    // Create checkbox button in ingredient div
    checkbox.addEventListener('click', () => {
        toggleIngredient(ingredient.text)
        saveRecipes()
        renderIngredients(recipeId)
    })

    // Setup ingredient text
    ingredientText.textContent = ingredient.text
    containerEl.appendChild(ingredientText)

    // Setup the remove button
    removeButton.textContent = 'remove'
    removeButton.classList.add('button', 'button--text')
    ingredientEl.appendChild(removeButton)
    // Create remove button in ingredient div
    removeButton.addEventListener('click', () => {
        removeIngredient(ingredient.text)
        saveRecipes()
        renderIngredients(recipeId)
    }) 

    return ingredientEl
}

const renderIngredients = (recipeId) => {
    // Grab the ingredient display from the DOM
    const ingredientList = document.querySelector('#ingredients-display')
    const recipe = getRecipes().find((item) => {
        return item.id === recipeId
    })

    // Iterate through the list of ingredients on the page and render all items from recipeDOM
    recipe.ingredients.forEach((ingredient) => {
        const recipeDOM = generateIngredientDOM(ingredient)
        ingredientList.appendChild(recipeDOM)
    })
}

renderIngredients(recipeId)

我认为问题源于我的renderIngredients函数,但是我不知道如何解决它。同样,当我刷新页面时,我希望显示结果,但是我想避免使用location.reload。我期望removeIngredient函数能够通过单击按钮来删除成分,并且页面会通过renderIngredients函数进行刷新。还期望toggleIngredient函数仅在我选中的成分旁边显示一个复选框,但这不是正在发生的情况。当我使用addIngredient函数时,发生了相同的事情,正在添加成分,但是页面上已经存在的成分被复制。

1 个答案:

答案 0 :(得分:1)

我想您想在再次添加元素之前清除列表:

ingredientList.innerHTML = "";