Appearance
标记模板字面量
本节目标:理解“标记模板字面量”的核心思路,并能把它用于实际开发或面试表达。 1. html 模板字面量用法代码片段 你在 HMenu 的 render 方法中使用了以下代码: render() { this.style.setProperty('--menu-flex-direction', this.mode === 'horizontal' ? 'row' : 'column'); return html
\<style\> :host { --menu-flex-direction: column; display: block; } [part="menu"] { display: flex; flex-direction: var(--menu-flex-direction); } [part="submenu"][data-expanded="true"] { display: block; } \</style\> \<div part="menu" role="menu"\> ${this.items.map((item) =\> this.renderItem(item, 0))} \</div\>;}
- 标记模板字面量(Tagged Template Literals):
- html 是一个函数,放在模板字面量前面,表示这是一个标记模板字面量。
- 标记模板字面量的语法是 tag...``,其中 tag 是一个函数,模板字面量作为参数传递给这个函数。
- 在你的代码中,html 函数定义在 lit-html.ts 中: export function html(strings: TemplateStringsArray, ...values: TemplateValue[]): Template { return { strings, values };}
- 当你写 html...`` 时,JavaScript 会将模板字面量拆解为两部分传递给 html 函数:
- strings:模板字符串的静态部分(TemplateStringsArray 类型),例如 ["<style>...", "</style><div part="menu" role="menu">", "</div>"]。
- values:插值部分(${...} 的值),例如 [this.items.map((item) => this.renderItem(item, 0))].
- html 函数将这些部分封装为一个 Template 对象 { strings, values },供 renderTemplate 渲染。
- 作用:
- html 模板字面量是 Lit 的核心功能,用于定义组件的 DOM 结构。
- 它允许你以声明式的方式编写 HTML 模板,同时支持动态插值(${...})和事件绑定(@click)。
- renderTemplate 会解析这个模板,生成高效的 DOM 更新。
执行过程
- render 方法调用 html...``,生成一个 Template 对象: { strings: [ "<style>\n :host {\n --menu-flex-direction: column;\n display: block;\n }\n [part="menu"] {\n display: flex;\n flex-direction: var(--menu-flex-direction);\n }\n [part="menu-item"] {\n display: flex;\n align-items: center;\n padding: 0.5rem;\n }\n [part="menu-item-active"] {\n background-color: #e5e7eb;\n }\n [part="icon"] {\n margin-right: 0.5rem;\n }\n [part="label"] {\n flex: 1;\n }\n [part="badge"] {\n margin-left: 0.5rem;\n padding: 0.25rem 0.5rem;\n background-color: #ef4444;\n color: white;\n border-radius: 9999px;\n }\n [part="toggle"] {\n margin-left: 0.5rem;\n cursor: pointer;\n }\n [part="submenu"] {\n padding-left: 1rem;\n display: none;\n }\n [part="submenu"][data-expanded="true"] {\n display: block;\n }\n</style>\n<div part="menu" role="menu">\n ", "\n</div>" ], values: [this.items.map((item) => this.renderItem(item, 0))]}
- ReactiveElement 的 performUpdate 方法调用 renderTemplate,将模板渲染到 shadowRoot。
- renderTemplate 解析 strings 和 values,生成 DOM 结构,并处理动态插值和事件绑定。
