用 template + slot 实现可复用卡片结构,通过原生 dom 分发机制注入动态内容,配合 web components 封装、css 响应式截断与无障碍交互反馈,确保语义化、高性能与可访问性。

用 template + slot 实现可复用卡片结构
直接写死 HTML 的卡片没法换内容,也不方便传参。现代做法是用原生 template 标签定义结构骨架,配合 <slot></slot> 插入动态内容——不是靠 JS 拼字符串,而是靠浏览器原生的 DOM 分发机制。
常见错误是把整个卡片写成一个大字符串然后 innerHTML 注入,这样既丢失语义、又无法响应式更新、还容易 XSS。正确姿势是:
-
template写在页面顶部或单独文件中,只包含结构,不带逻辑 - 每个可替换区域用
<slot name="title"></slot>显式命名,避免顺序错乱 - 外部使用时用
<my-card><span slot="title">自定义标题</span></my-card>注入 - 别在
slot里放内联事件(如onclick),统一由组件内部监听slotchange或委托处理
用 customElements.define 封装为可交互的 card-component
光有结构不够,得让卡片能响应点击、状态切换、数据绑定。原生 Web Components 是最轻量且无框架依赖的方案,关键不是“写个 class”,而是控制好生命周期和属性反射。
容易踩的坑:直接在 connectedCallback 里操作 shadowRoot 但没检查是否已 attach;或者用 attributeChangedCallback 却没在 observedAttributes 列表里声明对应属性。
使用 Puppeteer + Chrome 将 HTML 渲染为中文 PDF,自动处理图表等待、Tab 展开、动画、测高、白边消除、防分页,适用于看板、报表、网页和交互图表转 PDF。
- 必须调用
this.attachShadow({ mode: 'open' }),否则样式隔离失效 - 想支持
selected属性控制选中态?得同时定义static get observedAttributes()并在attributeChangedCallback里同步更新内部aria-selected和 class - 点击区域要覆盖整张卡片?给根元素设
tabindex="0",并监听click和keydown(Enter/Space),不能只靠onclick - 别在
render()方法里反复innerHTML = ...,优先用document.createElement+appendChild或replaceChildren
卡片内图片与文字的响应式截断必须靠 CSS,别碰 JS
很多团队用 JS 计算字符数再截断描述文本,结果字体缩放时溢出、中英文混排时长度错乱、屏幕阅读器读到不完整句子。真正的稳定解法是纯 CSS 控制。
性能影响很实际:JS 截断每渲染一张卡就要跑一遍 layout,10 张卡就是 10 次重排;而 -webkit-line-clamp 是渲染引擎原生能力,开销几乎为零。
- 文字两行截断必须同时写这四条:
display: -webkit-box、-webkit-box-orient: vertical、-webkit-line-clamp: 2、overflow: hidden - 父容器不能是
display: flex且没设min-height: 0,否则-webkit-line-clamp失效 - 图片容器加
aspect-ratio: 16 / 9,img设width: 100%; height: 100%; object-fit: cover,避免上传不同比例图导致卡片高度跳变 - 不支持
aspect-ratio的旧环境(如 Safari ≤14.5)用padding-top: 56.25%+position: relative容器 +position: absolute图片 fallback
交互反馈必须区分鼠标与键盘,:focus-visible 不能省
用户点一下没反应,或键盘 Tab 到卡片却看不到焦点框,这是无障碍硬伤。很多项目只写 :hover 和 :focus,结果鼠标用户看到蓝框、键盘用户也看到蓝框,体验割裂。
真正可用的交互反馈,核心是分通道设计:鼠标悬停用 transform: translateY(-2px) + box-shadow,键盘聚焦用清晰 outline,激活态(按下瞬间)用微位移模拟按压感。
- 必须用
:focus-visible替代:focus,现代浏览器自动判断输入方式,不干扰鼠标用户 -
:active动效只该用transform或background-color,禁用top/margin-top——会触发 layout,滚动卡顿 - 整张卡片可点?把
<a></a>或<button></button>设为display: block包裹全部内容,别用div+onclick - 如果卡片只是展开面板,必须用
<button type="button"></button>并加aria-expanded和aria-controls
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










