正确使用 template 标签需预声明结构、设唯一 id 并置于 head/body 顶部,用 clonenode(true) 安全复用;constructor 中仅调 super() 和 attachshadow;attributechangedcallback 需配合 observedattributes 声明监听属性;slot 分发依赖 light dom 子节点命名匹配。

template 标签怎么用才不踩坑
直接把 HTML 写进 innerHTML 里再 clone 是常见错误,容易漏掉样式、丢失事件绑定,还可能引入 XSS 风险。正确做法是用 <template></template> 预声明结构,它不会被渲染,也不会执行脚本,天然安全。
-
<template id="card-template"></template>必须有唯一id,且放在或顶部(不能在 shadow DOM 里嵌套) - 模板内
<style></style>会随content.cloneNode(true)一起进入 shadowRoot,样式自动隔离 - 别用
document.querySelector('#card-template').innerHTML—— 这会绕过 template 的语义,失去 script 过滤能力 - 如果模板含动态占位符(如
{{title}}),得靠 JS 替换,不是靠浏览器解析;原生 template 不支持数据绑定
constructor 里能干啥、不能干啥
constructor 是组件实例化第一站,只做最轻量的初始化:调 super()、挂 shadowRoot、拿模板内容。任何涉及 DOM 查询、属性读取、异步操作都该往后挪。
- ✅ 必须调
super(),否则继承链断裂 - ✅ 必须立即调
this.attachShadow({ mode: 'open' }),晚一秒样式就可能泄漏 - ❌ 别在
constructor里读this.getAttribute('xxx')—— 此时属性还没同步到实例,返回null - ❌ 别在
constructor里写this.shadowRoot.innerHTML = '...'—— 虽然不报错,但破坏了 template 复用性和可维护性 - ❌ 别发起 fetch 或 setTimeout —— 构造函数不该有副作用
attributeChangedCallback 怎么监听才有效
想让组件响应 HTML 属性变更(比如 <my-card title="Hello"></my-card> → <my-card title="Hi"></my-card>),光写 attributeChangedCallback 不够,必须先声明哪些属性值得监听。
- 必须用静态 getter
static get observedAttributes()显式列出,比如return ['title', 'avatar'] - 没列进去的属性(如
class、style)变更不会触发该回调 - 回调里别直接操作 light DOM(比如
this.querySelector('h3')),应走this.shadowRoot.querySelector('h3') - 注意字符串比较陷阱:
oldValue === newValue在首次初始化时可能都是null,建议用newValue !== oldValue判断变化 - 如果属性值是 JSON 字符串(如
data='{"id":1}'),需手动JSON.parse(newValue),原生不自动解析
slot 内容为什么没显示出来
写了 <slot></slot> 却看不到传入的内容,大概率是 slot 名称不匹配或投影时机不对。slot 不是“插入”,而是“分发”——它依赖 light DOM 子节点的存在和命名。
- 外部使用时要显式带
slot属性:<my-card><p slot="desc">副标题</p></my-card> - shadow DOM 里对应位置写
<slot name="desc"></slot>,名字必须完全一致(区分大小写) - 没指定
name的 slot 是默认插槽,只能接收没有slot属性的子节点 - 别在
connectedCallback里动态生成 slot 元素再 append —— 浏览器不会识别为 slot 内容,得靠 light DOM 原生结构 - 如果组件需要渲染后端返回的富文本 HTML,
<slot></slot>无效,得用DOMParser解析后手动appendChild到shadowRoot
真正难的不是写完一个能跑的组件,而是判断什么时候该用原生、什么时候该切到 Lit —— 比如带表单验证、多状态切换、频繁 re-render 的场景,手写 attributeChangedCallback + render() 很快就会失控。别硬扛。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











