# HTML innerHTML 事件处理器反模式

## 问题

在HTML中通过 `innerHTML` 字符串拼接构建带 `onclick` 的元素时，中文内容
和引号转义极易出错，表现为：

1. 点击事件不触发
2. JS语法错误（`missing ) after argument list`）
3. 元素渲染正常但交互失效

## 根因

```javascript
// ❌ 当 group='王向阳课题组', product='BR1D303' 时：
var imgKey = f.group + '_' + f.product;
div.innerHTML = '<div onclick="uploadImg(\'' + imgKey + '\')">上传</div>';
// 渲染结果：<div onclick="uploadImg('王向阳课题组_BR1D303')">上传</div>
// → 中文内容可能被URL编码或触发HTML解析异常
```

更复杂的场景（带 `style` 属性的HTML标签作为字符串传给 `onclick`）：
```javascript
// ❌ 多层转义：字符串 → HTML属性 → JS字符串 → HTML标签 → CSS属性
var savedImg = 'data:image/...';
div.innerHTML = '<div onclick="show(\'' + savedImg + '\')"><img src="' + savedImg + '"></div>';
```
等价于手写 `\\\\\"` 四层转义，必出错。

## 正确做法

### 1. DOM API 绑定事件

```javascript
// ✅ 用 createElement + 属性赋值 + onclick 绑定
var div = document.createElement('div');
div.className = 'pos-card';
div.setAttribute('data-key', key);
div.onclick = function() { openShareCard(this.getAttribute('data-key')); };

// ✅ 子元素也如此
var uz = document.getElementById('uz-' + key);
uz.onclick = function(e) { e.stopPropagation(); uploadImg(this.id.replace('uz-', '')); };
```

### 2. 数字键替代字符串键

当元素需要携带标识符传给事件处理器时，用数组索引或数字ID而非中文组合字符串：

```javascript
// ✅ 用列表索引
list.forEach(function(item, i) {
  var key = String(i);
  element.setAttribute('data-key', key);
});
```

### 3. 外层HTML用innerHTML，事件处理器用DOM绑定

```javascript
// ✅ 折中方案：HTML结构用 innerHTML（快速），事件用 DOM 绑定（可靠）
div.innerHTML =
  '<div class="header">' + name + '</div>' +
  '<div class="upload-zone" id="uz-' + key + '"></div>';

document.getElementById('uz-' + key).onclick = function(e) {
  e.stopPropagation();
  uploadImg(key);
};
```

## 适用场景

任何需要以下条件的HTML页面：
- 动态生成元素列表
- 元素携带中文/特殊字符标识
- 元素需要点击事件处理器
- 事件处理器需要防止向父元素冒泡（`stopPropagation`）

## 已知受影响页面

- `工具/科研测试反馈.html` — 正反馈卡片上传区（已修复）
- `工具/宝锐统一工作平台.html` — 所有事件处理器均使用DOM绑定（正确）
