代码之家  ›  专栏  ›  技术社区  ›  JackJack

更改数组属性后呈现数组项

  •  0
  • JackJack  · 技术社区  · 5 年前

    在对数组中的元素进行更改后,我在重新呈现数组中的项时遇到问题。无论是通过推送添加,还是通过拼接删除,当数组再次呈现在页面上时,都会有更多的项被添加到数组中。因此,如果我推到数组上,则会添加该项,但旧项随后会复制到数组中。当我移除项目时会发生类似的事情。该项看起来已被删除,但数组中的元素将显示在页面上,然后它们将被复制,拼接的项将消失。

    我试图避开一个位置。重新加载(“/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 功能通过单击按钮删除成分,页面将使用 渲染重述 功能。也期望 切换为灰色 函数的作用是在我选中的原料旁边显示一个复选框,但事实并非如此。当我使用 addIngredient 功能,正在添加成分,但页面上已存在的成分正在复制。

    1 回复  |  直到 5 年前
        1
  •  1
  •   Jonas Wilms    5 年前

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

    ingredientList.innerHTML = "";