在 `success` 回調中直接拼接超長 HTML 字串,包含業務邏輯、分頁算法、DOM 操作,代碼行數達百行,極難維護。
| 維度 | 字串拼接法 | 模板引擎/組件化 |
|---|---|---|
| 可讀性 | 極差:HTML/JS/業務邏輯耦合,引號轉義地獄 | 優:模板與邏輯分離,語法高亮、縮進正常 |
| 可維護性 | 修改一個 class 名需在 JS 字串中搜尋替換,極易漏改 | 修改模板文件即時生效,不動 JS 邏輯 |
| 錯誤率 | 高:少引號、標籤未閉合、XSS 風險 (未轉義數據) | 低:模板引擎自動轉義,語法錯誤編譯期發現 |
| 性能 | 大字串拼接佔用內存,`innerHTML` 觸發完整重解析 | 虛擬 DOM 差異更新 (Vue/React) 或預編譯模板函數 |
| 調試體驗 | 斷點只能停在拼接行,無法檢查中間 HTML 結構 | 可獨立渲染模板預覽,Vue DevTools 等工具支持 |
若暫不引入框架,立即可行的改進:
// 1. 定義模板片段變量,語義化命名
const headerTpl = `
<div class="news comWidth">
<div class="news_top">...</div>
<div class="news_list" id="news_list"></div>
<div id="pageGro" class="cb"></div>
</div>`;
const itemTpl = (data) => `
<a href="javascript:go(${data.id});" class="title">
<div class="news_content">
<img src="../images/hzhb04.png">${data.title}
<i>${data.createtime}</i>
</div>
</a>`;
// 2. 渲染邏輯分離
success: function(result) {
$('#news_box').html(headerTpl); // 一次性設置容器
const $list = $('.news_list');
result.data.forEach(d => $list.append(itemTpl(d))); // 循環追加項目
// 分頁渲染同理提取 pageTpl(current, total, onChange)
renderPagination(result.count, 10, 4, 0, (page) => loadPage(page));
}
// 3. 分頁邏輯提取為純函數
function renderPagination(total, pageSize, linkCount, currentPage, onPageClick) {
// 計算 startPage, endPage ...
// 生成 HTML 字串 ...
$('#pageGro').html(pageHtml);
}
原代碼直接拼接 `data.title` 等後端數據,**極高風險 XSS**。任何模板方案必須**上下文感知轉義** (HTML 實體編碼、JS 字串轉義、URL 編碼)。現代框架默認轉義,手動拼接必須用 `DOMPurify` 或自寫 `escapeHtml`。
AJAX 返回數據,前端負責渲染是正確架構。但**字串拼接 HTML 是技術債**,請立即採用「模板變量化」過渡,並規劃引入模板引擎或組件框架。