v-for用于遍历数组、对象、数字等数据源批量渲染结构,必须配合唯一且稳定的key(如item.id)以确保dom高效更新和状态正确绑定。

模板怎么把数据“塞”进组件里,而不是硬编码
HTML本身不解析数据,所谓“模板与数据解析”,本质是靠外部机制注入。纯静态HTML文件里写死的<h2>用户列表</h2>永远不变;要让它随数据变,必须有执行上下文——要么后端渲染(如Go的html/template),要么前端JS运行时(如Vue的v-for)。关键不是“HTML支持模板”,而是“谁在什么时候、用什么规则把数据填进去”。
常见错误现象:
直接在HTML里写{{name}}却没引入任何模板引擎,浏览器原样显示双大括号
用fetch()拉回JSON,但只拼字符串插入innerHTML,没做XSS过滤
Go模板里传入结构体字段名拼错,比如传UserName却在模板里写.username(大小写敏感)
使用场景决定解析方式:
服务端渲染(SSR):Go/Python/Rust等后端生成完整HTML响应,{{template "header" .}}在服务端就展开
客户端渲染(CSR):HTML只留容器,JS用document.querySelector('.cmp-list__items').innerHTML = items.map(...)动态填充
混合模式:Vite插件预编译<!--@include header.html-->,构建时合并,不依赖运行时
性能影响很实在:
服务端解析快(一次生成,缓存友好),但首屏依赖后端延迟
客户端解析灵活(可按需加载数据),但首次渲染空白时间长,SEO不友好
纯静态模板预处理(如Node脚本替换<!-- include: nav.html -->)无运行时开销,但改数据要重新构建
为什么data-* 属性比全局变量更适合传配置
在不引入框架的前提下,data-属性是HTML组件间传递轻量配置最自然的方式。它把“这个卡片要不要带关闭按钮”这种决策,从JS代码里抽出来,写在HTML里,既声明式又可调试。
常见错误现象:
在JS里写const theme = 'dark';然后硬编码到所有cmp-card逻辑里,换主题就得改JS
用class="card-dark"代替data-theme="dark",导致样式类名和行为逻辑耦合,后续加动画或JS响应难分离
把整个配置对象序列化成data-config='{"delay":500,"closable":true}',但没做JSON.parse()容错,遇到单引号就报错
参数差异要注意:data-closable="false"会被JS读成字符串"false",不是布尔值false,得手动转换:el.dataset.closable === 'true'data-delay="500"读出来是字符串,要用Number(el.dataset.delay)转数字
驼峰命名如data-allowAutoClose会自动转成el.dataset.allowautoclose(全小写+连字符分隔),别指望保持大小写
兼容性没问题:dataset API在IE11+都支持,比getAttribute('data-xxx')更简洁,且自动处理命名转换。
Go模板里{{template}}和{{define}}怎么配对才不报错
Go的html/template不是“包含文件”,而是“定义并引用命名模板”。{{template "name" .}}必须对应一个已{{define "name"}}的块,且该块必须已解析进同一个template.Template对象中。
常见错误现象:
主模板里写{{template "sidebar" .}},但ParseFiles("main.html")没同时加载sidebar.html,运行时报template: "sidebar" not defined
子模板文件里漏写{{define "sidebar"}},只写了HTML内容,结果整个文件被当顶层模板,{{template}}找不到目标
两个模板文件都定义了{{define "header"}},但用template.New("main").ParseFiles("a.html", "b.html"),后者覆盖前者,静默丢失
实操要点:
用template.Must(template.New("main").ParseFiles("main.html", "header.html", "footer.html"))一次性加载全部,确保所有{{define}}可见
子模板文件不必有标签,只写{{define "content"}}<div>...</div>{{end}}即可
传递数据时,{{template "header" .}}中的.是当前作用域数据,若子模板需要不同结构,先用{{with .User}}切换上下文,再{{template "user-card" .}}
注意:Go模板不支持嵌套{{template}}的动态名称,{{template $name .}}会报错,名称必须是字面量字符串。
Vue里v-for和HTML语义化标签怎么一起用不翻车
Vue的v-for生成列表时,容易忽略HTML语义约束。比如用<div v-for="item in list">替代<code><li>,破坏了列表结构,影响无障碍访问和SEO。
常见错误现象:
在<ul></ul>里直接v-for循环<div>,浏览器自动补<code><li>但DOM结构混乱,CSS选择器失效
用<section v-for="post in posts"></section>但每个section没配<h2></h2>标题,违反section必须有主题的语义要求
动态生成表格行时,v-for放在<tr>上没问题,但若放在<code><table>上,就会多出一堆<code><table>标签<p>正确姿势:<br>列表必须用<code><ul><li v-for="item in items">{{item.name}}</li></ul>,别省略<li>
文章流用<article v-for="post in posts"><h2>{{post.title}}</h2>...</article>
表格行用<tbody><tr v-for="row in data"><td>{{row.col1}}</td></tr></tbody>,别让v-for跨表头/表尾
容易被忽略的点:Vue 3里v-for必须带:key,且key要稳定唯一;用:key="item.id"比:key="index"更安全,否则数组重排时DOM复用会出错。











