根本原因是html文档编码与js字符串实际编码不一致:浏览器按utf-8解析html,但js字符串若被错误当作gbk或iso-8859-1处理后再插入dom,就会乱码;关键在http响应头是否声明charset=utf-8,而非js写法本身。

动态插入中文时 DOM 显示 乱码
根本原因不是 JS 本身,而是 HTML 文档的字符编码与 JS 字符串实际编码不一致。浏览器解析 HTML 时已按 UTF-8 解码,但若 JS 字符串在生成或传输过程中被错误当作 GBK 或 ISO-8859-1 处理,再插入 DOM 就会变成 。
- 常见现象:用
element.innerHTML = "你好"或textContent插入后显示为 、、,但直接写死在 HTML 中正常 - 本质是字符串“源”出了问题:可能是 AJAX 响应头没设
charset=utf-8,也可能是后端返回了 GBK 编码的 JSON,JS 却当 UTF-8 解析 - Node.js/Express 中用
res.json()默认带Content-Type: application/json; charset=utf-8,但用res.send({msg: "你好"})不一定——它可能走默认text/html或无 charset 的application/json - Python Flask 默认响应头不含
charset,需显式加:return jsonify({...}).headers.set('Content-Type', 'application/json; charset=utf-8')
fetch / XMLHttpRequest 返回中文乱码
关键不在 JS 怎么写,而在 HTTP 响应头是否明确声明 charset=utf-8。浏览器对 text/plain 或未声明 charset 的 application/json 会 fallback 到系统默认编码(Windows 是 GBK)。
- 检查方式:
F12 → Network → 点开请求 → Headers → Response Headers → Content-Type,确认值含charset=utf-8 - 如果后端没配,前端不能“修复”:你无法让
fetch().then(r => r.text())强制按 UTF-8 解码一个实际是 GBK 的响应体 - PHP 后端必须在输出前加:
header('Content-Type: application/json; charset=utf-8');(且不能有任何输出在header()之前,包括 BOM) - Node.js Express 中避免用
res.send()直接发中文对象,改用res.json()或手动 set:res.set('Content-Type', 'application/json; charset=utf-8').send(JSON.stringify({...}))
innerHTML 插入模板字符串时中文变乱码
这通常和 HTML 文件本身的编码无关,而是字符串拼接过程中混入了非 UTF-8 源数据,比如从表单 input.value 读取、或从 localStorage 读取旧数据时没处理好。
-
localStorage存的是字符串,但早期某些浏览器(IE)存 GBK 编码的字符串后,读出来仍是原始字节流,JS 无法自动转码 - 表单提交时若
<form accept-charset="GBK"></form>,input.value可能已是乱码字符串,再插进 DOM 必然乱 - 避免拼接:
element.innerHTML = `<div>${data.name}</div>`—— 如果data.name来自不可信源,优先用textContent+createElement - 安全做法:
const span = document.createElement('span'); span.textContent = data.name; element.appendChild(span);(绕过 HTML 解析,杜绝双解码风险)
Vue / React 动态渲染中文乱码
框架层一般不导致乱码,但 SSR(服务端渲染)场景下,Node.js 读取 HTML 模板文件时若没指定编码,会按系统默认(如 Windows 的 cp1252)读取 UTF-8 文件,导致字符串内部已损坏。
- Node.js 读文件必须显式指定
encoding='utf8':fs.readFileSync('index.html', 'utf8'),否则默认buffer,易出错 - Webpack/Vite 构建时,若
html-webpack-plugin加载的模板含 BOM,部分 loader 可能误判编码;建议用file -i index.html验证,删 BOM - Vue SFC 中
<template></template>写死中文没问题,但v-html绑定的内容若来自后端未声明 charset 的接口,一样乱——和原生innerHTML同理 - React 的
dangerouslySetInnerHTML同样依赖内容本身是合法 UTF-8 字符串,不负责转码
最常被忽略的一点:乱码往往不是“某一行代码错了”,而是“整个数据链路中某一处没声明 charset”,从后端响应头、文件读取方式、到前端 fetch 配置,任一环缺失都会导致下游全乱。别只盯着 JS 插入那行,先用 curl -I 或 F12 看响应头。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











