You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring项目中如何局部刷新表单/fieldset,解决删除后视图更新问题

问题描述

我在Spring项目中有一个index.html文件,包含两个表单。第一个表单输入姓名并提交后,姓名会传递到第二个表单,该表单关联数据库并在fieldset中展示数据。目前两个按钮的情况:

  • ADD to DB:点击添加条目后可立即看到新增项,功能正常
  • DELETE an item from DB by ID:能正常删除数据库中的条目,但视图不会刷新,需整页刷新才能看到结果,而整页刷新会回到第一个表单页面。我需要修改DELETE函数,实现仅刷新表单或fieldset而非整页。

原代码如下:

<!DOCTYPE html>
<html lang="en" xmlns:https="http://www.w3.org/1999/xhtml" xmlns:http="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>SHOPPING LIST</title>
    <link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css"
          integrity="sha384-nn4HPE8lTHyVtfCBi5yW9d20FjT8BJwUXyWZT9InLYax14RDjBj46LmSztkmNP9w" crossorigin="anonymous">
</head>
<body>
<main style="width: 40%; margin: 0 auto">
    <div id="welcome" style="text-align: center">
        <h1>Introduce yourself</h1>
    </div>
    <form id="welcomeForm" class="pure-form pure-g pure-form-aligned">
       <input class="pure-input-rounded pure-u-1" name="name" placeholder="name" id="text_name">
       <button id="welcomeFormBtn" class="pure-button pure-button-primary pure-u-1">Submit</button>
    </form>
    <form id="AddForm" class="pure-form" style="text-align: center; display: none">
        <fieldset>
            <input id="name" class="pure-input-rounded pure-input-2-3" style="width: available" placeholder="name">
            <input id="amount" class="pure-input-rounded pure-input-2-3" style="width: available" placeholder="amount">
            <input id="uom" class="pure-input-rounded pure-input-2-3" style="width: available" placeholder="unit of measure">
            <input id="idToDel" type="number" class="pure-input-rounded pure-input-2-3" style="width: available" placeholder="Please provide an id to delete">
        </fieldset>
        <fieldset>
            <button id="addProduct" class="pure-button pure-button-primary">POST</button>
            <button id="delProduct" class="pure-button pure-button-primary">DELETE</button>
            <br>
            <button id="print-btn"  style="width: 50px; height: 50px; border-radius: 50%"><img style="width: 40px; height: 40px" src="https://cdn-icons-png.flaticon.com/512/3233/3233446.png" alt="PRINT"></button>
        </fieldset>
        <fieldset id="allProducts" >
          </fieldset>
    </form >
</main>
<script>
    const API_URL = 'http://localhost:8080';
    const API_URL_ADD = `${API_URL}/api`;
    const API_URL_ALL = `${API_URL_ADD}/list`;
    const pName = document.getElementById('name');
    const pUom = document.getElementById('uom');
    const pAmount = document.getElementById('amount');

    AddFunction();

    fetch(API_URL_ALL)
        .then(processOkResponse)
        .then(list => list.forEach(createNewProduct))

    document.getElementById('addProduct').addEventListener('click', (event) => {
        event.preventDefault();
        fetch(API_URL_ALL, {
            method: 'POST',
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            body: JSON.stringify({ name: pName.value, type : pUom.value, amount: pAmount.value })
        })
            .then(processOkResponse)
            .then(createNewProduct)
            .then(() => pName.value = '')
            .then(() => pAmount.value = '')
            .then(() => pUom.value = '')
            .catch(console.warn);
    });

    function createNewProduct(product) {
        const label = document.createElement('label');
        const l1 = document.createElement('label');
        const l2 = document.createElement('label');
        const l3 = document.createElement('label');
        const l4 = document.createElement('label');
        label.classList.add('label');
        l1.appendChild(document.createTextNode(`  ID:${product.id}. `));
        l2.appendChild(document.createTextNode(` ${product.name} `));
        l3.appendChild(document.createTextNode(` ${product.amount} `));
        l4.appendChild(document.createTextNode(` ${product.type} `));
        label.appendChild(l1).appendChild(l2).appendChild(l3).appendChild(l4)
        document.getElementById('allProducts').appendChild(label);
        label.style.display= 'table';
        label.style.paddingLeft='40%';
        label.style.wordSpacing='30%';
            }

    document.getElementById('delProduct').addEventListener('click', (event) => {
        event.preventDefault();
        removeTodo();
    });

    function removeTodo() {
        const d = document.getElementById('idToDel').value;
        fetch(`${API_URL_ALL}/${d}`, { method: 'DELETE' })
            .then(processOkResponse)
            .catch(console.info)
    }

    function AddFunction(){
        const welcomeForm = document.getElementById('welcomeForm');

        document.getElementById('welcomeFormBtn').addEventListener('click', (event) => {
            event.preventDefault();
            const formObj = {
                name: welcomeForm.elements.name.value,
            };
            fetch(`${API_URL_ADD}?${new URLSearchParams(formObj)}`)
                .then(response => response.text())
                .then((text) => {
                    document.getElementById('welcome').innerHTML = `
                <h1>${text}</h1>
            `;
                    welcomeForm.remove();
                    document.getElementById('AddForm').style.display = 'block';
                    });
        });
    }

    document.getElementById('print-btn').addEventListener('click', (event) => {
        event.preventDefault();
        const f = document.getElementById("allProducts").innerHTML;
        const a = window.open();
        a.document.write(document.getElementById('welcome').innerHTML);
        a.document.write(f);
        a.print();
    })

    function processOkResponse(response = {}) {
        if (response.ok) {
            return response.json();
        }
        throw new Error(`Status not 200 (${response.status})`);
    }
</script>
</body>
</html>
解决方案

下面提供两种可行的修改方案,任选其一即可解决问题:

方案一:删除后直接移除对应DOM元素(高效)

修改removeTodo函数,在删除成功后找到对应ID的元素并从页面移除:

function removeTodo() {
    const d = document.getElementById('idToDel').value;
    fetch(`${API_URL_ALL}/${d}`, { method: 'DELETE' })
        .then(processOkResponse)
        .then(() => {
            // 清空删除ID输入框
            document.getElementById('idToDel').value = '';
            // 找到包含目标ID的标签并移除
            const productLabels = document.querySelectorAll('#allProducts .label');
            productLabels.forEach(label => {
                if (label.textContent.includes(`ID:${d}.`)) {
                    label.remove();
                }
            });
        })
        .catch(console.info)
}

说明:这种方式不用重新请求接口,直接操作DOM更新视图,响应更快,适合数据一致性要求不高的场景。

方案二:删除后重新请求最新数据并渲染(数据同步性高)

如果希望视图和数据库数据完全同步,可选择删除成功后重新获取全部数据并渲染:

function removeTodo() {
    const d = document.getElementById('idToDel').value;
    fetch(`${API_URL_ALL}/${d}`, { method: 'DELETE' })
        .then(processOkResponse)
        .then(() => {
            // 清空删除ID输入框
            document.getElementById('idToDel').value = '';
            // 清空当前展示的所有产品
            const allProductsContainer = document.getElementById('allProducts');
            allProductsContainer.innerHTML = '';
            // 重新请求最新数据并渲染
            return fetch(API_URL_ALL);
        })
        .then(processOkResponse)
        .then(list => list.forEach(createNewProduct))
        .catch(console.info)
}

说明:这种方式会重新拉取数据库中的最新列表,确保视图数据和数据库完全一致,适合多用户操作或数据频繁变更的场景。

内容的提问来源于stack exchange,提问作者Jumperro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 21:15:34