JSP页面通过JavaScript展示Java List元素时重复显示最后一项的问题
解决JSP动态生成标签重复显示最后一个姓名的问题
嘿,我来帮你搞定这个所有标签都显示最后一个姓名的问题!你遇到的坑其实是服务器端JSP执行时机和客户端JS执行时机不匹配,再加上代码里的几个小错误,咱们一步步拆解:
问题根源在哪?
- JS字符串拼接语法错误:你在
html()方法里的字符串写法有问题,服务器端输出的<%= t.getNames()%>没有和前后的字符串用+连接,导致渲染后的JS代码直接变成类似'<h1 name="textbox1" >Name:' 张三 '</h1',这在JS里是语法错误,浏览器会忽略报错的代码,最后可能只有最后一次循环的代码(碰巧没触发致命错误)生效。 - 重复的DOM ID:每次创建div都设置同一个
id="ALPHA",HTML里ID必须唯一,这会导致DOM元素冲突,后续元素要么无法正确插入,要么覆盖之前的内容。 - 全局变量覆盖:每个
<script>块里都定义var newTextBoxDiv1,这个变量属于全局作用域,后面的循环会覆盖前面的变量,最终只有最后一次的变量被保留执行。
修正后的优雅方案
推荐你把服务器端的列表一次性转成JSON格式传给JS,再用JS遍历生成标签,既避免了循环生成JS的问题,也更符合前后端数据传递的最佳实践。
步骤1:将Java集合转成JSON字符串
首先确保项目里有JSON处理库(比如Gson或Jackson),然后在JSP里把List转成JSON:
<%@ page import="com.google.gson.Gson" %> <% List<SetsAndGetsData> list = (ArrayList<SetsAndGetsData>) request.getAttribute("Persons"); Gson gson = new Gson(); // 把集合转成JSON字符串 String personsJson = gson.toJson(list); %>
步骤2:用JS遍历JSON生成标签
在单独的<script>块里处理这个JSON数组,动态生成所有标签:
<script type="text/javascript"> // 把服务器端生成的JSON字符串转成JS数组 var persons = <%= personsJson %>; // 获取要插入标签的容器 var container = document.getElementById("TextBoxesGroup1"); // 遍历每个人员数据 persons.forEach(function(person, index) { // 创建div,给每个div设置唯一ID var newDiv = document.createElement('div'); newDiv.id = 'ALPHA-' + index; // 用索引保证ID唯一 // 创建h1标签并设置内容 var nameHeading = document.createElement('h1'); nameHeading.name = 'textbox1'; // 用textContent避免HTML注入风险 nameHeading.textContent = 'Name: ' + person.names; // 把h1加到div,再把div插入容器 newDiv.appendChild(nameHeading); container.appendChild(newDiv); }); </script>
无JSON库的替代方案
如果暂时没有JSON库,也可以直接用JSP循环生成JS数组:
<script type="text/javascript"> var persons = [ <% for (int i = 0; i < list.size(); i++) { SetsAndGetsData person = list.get(i); // 转义单引号避免JS语法错误 String escapedName = person.getNames().replace("'", "\\'"); %> {names: '<%= escapedName %>'}<%= i < list.size()-1 ? "," : "" %> <% } %> ]; // 遍历生成标签的代码和上面一致 var container = document.getElementById("TextBoxesGroup1"); persons.forEach(function(person, index) { var newDiv = document.createElement('div'); newDiv.id = 'ALPHA-' + index; var nameHeading = document.createElement('h1'); nameHeading.name = 'textbox1'; nameHeading.textContent = 'Name: ' + person.names; newDiv.appendChild(nameHeading); container.appendChild(newDiv); }); </script>
如果你坚持用原循环方式的修正版
要是你不想改结构,也可以直接修正原代码的语法和ID问题:
<% List<SetsAndGetsData> list = (ArrayList<SetsAndGetsData>) request.getAttribute("Persons"); int idx = 0; for (SetsAndGetsData t : list) { idx++; // 转义姓名里的单引号 String escapedName = t.getNames().replace("'", "\\'"); %> <script type="text/javascript"> var newTextBoxDiv1 = $(document.createElement('div')).attr("id", 'ALPHA-<%= idx %>'); // 用+正确连接字符串 newTextBoxDiv1.html('<h1 name="textbox1" >Name: <%= escapedName %></h1>'); newTextBoxDiv1.appendTo("#TextBoxesGroup1"); </script> <% } %>
不过这种方式不如JSON方案优雅,容易出现变量覆盖和语法问题,还是更推荐前面的方案。
内容的提问来源于stack exchange,提问作者Sajjad Haider
相关产品推荐
相关产品推荐

