尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

一文讲透 lit-html 渲染原理:3 个渲染步骤,让模板引擎只改该改的 DOM

一文讲透 lit-html 渲染原理:3 个渲染步骤,让模板引擎只改该改的 DOM 一文讲透 lit-html 渲染原理3 个渲染步骤让模板引擎只改该改的 DOM【免费下载链接】litLit is a simple library for building fast, lightweight web components.项目地址: https://gitcode.com/GitHub_Trending/li/litlit-html 是 Lit 的核心模板引擎它用极少的代码就能描述 UI并且在状态频繁变化时把 DOM 更新成本压到极低。读完这篇文章你能讲清楚 lit-html 的渲染流程如何运转以及你模板里每一处动态绑定到底在 DOM 上做了什么动作。为什么前端渲染里「只更新变化部分」这么重要 想象一个长列表页面数据每隔一秒变一次。如果每次变化都推倒整片 DOM 重新构建浏览器就得反复做布局、重绘——页面越大卡得越厉害。上面这张截图来自一个列表场景数据条目成千上万但同一时刻 DOM 里只保留可见的那十几条。它点出了一个朴素却关键的思路结构没变的部分别碰只重写值变了的地方。lit-html 快的根本原因就一句话首次渲染时把准备工作做透之后每次更新只去碰可能变化的位置而且值没变就干脆不碰。lit-html 模板引擎如何分离静态与动态✂️ 先看你平时是怎么写模板的// 写 UI 就像写填空题${} 外面的部分是固定骨架里面填的是会变的答案 const greet (name) htmlh1Hello, ${name}/h1;这一行背后是两个 Web 原生特性在干活模板字面量标签函数反引号前面的html是一个标签函数。JS 执行模板字符串时会自动把内容劈成两半——静态字符串数组h1Hello,和/h1这些骨架和动态值数组你填进去的name。html函数此刻几乎不干活只是把这两份东西外加一个类型标记打包成一个TemplateResult对象交出去。template元素浏览器自带的 HTML暂存柜。里面的内容不执行、不参与布局但随时可以克隆进文档变成活的节点。lit-html 把静态骨架就存在这里。 打个比方静态 HTML 被刻成一枚钢印动态值只是钢印上预留的空白位。钢印只刻一次每次渲染只是往空白位里填东西。lit-html 渲染流程拆解为什么首次之后的更新很快⚙️ 完整流程就三步刻钢印Prepare→ 盖章Create→ 填写Update。注意只有第三步是每次渲染都会跑的。首次渲染刻钢印与盖章刻钢印这一步lit-html 干了三件事把静态字符串拼成一段带标记的 HTML文本位置插一条标记注释属性位置给属性名加上特殊后缀把这段 HTML 塞进一个template元素让浏览器去解析然后遍历解析结果记下每一处空白位在第几个节点、叫什么属性、什么类型。盖章这一步把template里的内容克隆成文档片段放进页面并在每个空白位挂上一支对应类型的笔Part。这支笔以后就专门负责往这个位置写值。后续更新只遍历笔值没变就跳过✍️ 状态变了你再调用一次render()。lit-html 会在容器上发现这里盖过章了它会在容器元素上留一个记录于是直接跳过刻印和盖章只干填写按顺序走过每一支笔把新值递过去。// 你可以把更新阶段理解成这样 parts.forEach((part, i) part.setValue(newValue[i])); // 每支笔内部先和新旧值比对变了才真正写 DOM每支笔拿到新值后会先和上次写入的值做严格比较——没变化一个 DOM 操作都不做。所以演示里的计数器点一下按钮实际发生的只是把数字文本和 class 属性重写了一遍按钮本身纹丝不动。想把每一步对照源码细看官方设计文档里有完整的逐步图解dev-docs/design/how-lit-html-works.md。动态绑定的每种位置对应哪个 Part️ 不同位置的空白位挂着不同种类的笔。按场景记最牢标签内的文本如div${user.name}/div→ChildPart。出场率最高数字、字符串、嵌套子模板、节点列表都能渲染。属性值里如p class${cls}→AttributePart。通过 setAttribute 写入一个属性里塞了多个动态值时会拼好再一次性写入。布尔属性如?disabled${on}→BooleanAttributePart。为真就把属性加上为假就摘掉属性本身没有值。JS 属性如.value${text}→PropertyPart。直接给元素的 JS 属性赋值input.value text走的是属性通道而不是 HTML 属性通道。事件如click${handler}→EventPart。它用一个内部监听器对象占住位置即使你每次渲染传进新的函数引用也不会反复拆掉再挂监听器。标签本身如${tag}${...}→ElementPart。很少单独使用它是给动画这类自定义指令预留的插槽。种类虽然多共同点只有一个先比对、后写入。想翻它们的实现都在 packages/lit-html/src/lit-html.ts 里。模板缓存一次解析如何被处处复用 你大概会问同一个列表模板被 30 个组件共用难道要刻 30 次钢印不会。lit-html 用一个WeakMap做缓存而键正是模板的静态字符串数组。JS 引擎保证同一个模板字面量无论求值多少次它的字符串数组引用都是同一个——相当于每枚钢印都有固定不变的身份证号。于是第一次遇到某个模板时做完整刻印之后再来不管动态值换成1.jpg还是2.jpg都直接命中缓存、复用那枚钢印。变的只是盖章产生的实例每个渲染位置盖出自己的克隆、挂自己的一排笔互不干扰。一次解析、全局复用省下的既是时间也是内存。缓存本体在源码里就是一张WeakMap想亲眼确认可以打开 packages/lit-html/src/lit-html.ts 搜一下templateCache。要点小结lit 渲染流程记住三句话就够 用三句话收拢全文静态动态从源头分开静态 HTML 刻进一个template钢印动态值只留下被标记的空白位。首次渲染最重刻印 盖章此后每次渲染只做填写且值没变的笔一动不动。钢印以静态字符串数组为键缓存一次刻印全应用复用。这也就是 Lit 性能优化的底层逻辑对没变化的东西一分力气都不花。Lit 性能优化还在往哪走预编译把刻印挪到构建期完成运行时连这一步都省掉。原生模板实例化 API浏览器原生提供声明空白位的能力lit-html 就不用再手动遍历节点树去找标记。最后一点互动如果你觉得这篇帮你理清了 lit-html 的渲染原理欢迎点赞、收藏并关注后续更新不会错过。下一篇我们聊聊「如何给 lit-html 写自定义指令」让一支笔能干一百件事。我们下篇见【免费下载链接】litLit is a simple library for building fast, lightweight web components.项目地址: https://gitcode.com/GitHub_Trending/li/lit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表