
Sveltesvelte:document详解Document 级事件监听、属性绑定与 Attachments 用法【免费下载链接】svelteweb development for the rest of us项目地址: https://gitcode.com/GitHub_Trending/sv/sveltesvelte:document是 Svelte 提供的特殊元素用于在组件中直接监听挂载在document上的事件如只触发于 document 的visibilitychange、绑定 document 的只读属性如visibilityState以及对 document 使用 attachments。本文基于 Svelte 官方文档与编译器/运行时源码梳理其完整语法、可用的四个绑定属性、编译期校验规则以及底层监听与清理机制帮助你在页面可见性检测、全屏状态跟踪、指针锁定等场景中以声明式方式接入 document 级行为。基本语法与定位官方文档给出的两种基本用法如下svelte:document onevent{handler} /svelte:document bind:prop{value} /与svelte:window类似svelte:document存在的意义是有些事件只触发在document上典型如visibilitychange无法通过svelte:window捕获同时它也允许对document使用 attachments{attach}。文档中明确的约束是As withsvelte:window, this element may only appear the top level of your component and must never be inside a block or element.即svelte:document只能出现在组件的顶层不能位于任何块{#if}、{#each}等或元素内部。一个同时使用事件监听与 attachment 的完整示例svelte:document onvisibilitychange{handleVisibilityChange} {attach someAttachment} /事件监听从模板到运行时编译器如何处理从源码结构看svelte:document的处理分为分析与转换两个阶段分析阶段visitors/SvelteDocument.js 对该节点执行两项校验调用disallow_children禁止其携带任何子节点遍历属性事件属性onevent{handler}形式会经过check_global_event_reference检查而任何普通属性或展开属性都会直接抛出illegal_element_attribute编译错误。转换阶段3-transform 客户端的 SvelteDocument 访问器 将其交由通用的visit_special_element(node, $.document, context)处理——事件属性会被生成为初始化语句直接以document作为事件目标注册监听而不是渲染出任何真实 DOM 节点。错误边界可验证仓库中的校验测试印证了上述规则。例如 illegal_spread_element-documentscript let a {}; /script svelte:document {...a}/svelte:document对应的期望错误为{ code: illegal_element_attribute, message: svelte:document does not support non-event attributes or spread attributes }这说明svelte:document只接受事件属性与bind:指令既不支持普通属性也不支持{...spread}展开类似地document-binding-invalid-dimensions 等测试用例验证了在其上绑定clientWidth等尺寸属性同样会被拒绝。可绑定的四个属性全部只读文档列出了svelte:document支持绑定的属性且均为只读属性对应的 document 属性变更通知事件源码标注activeElementdocument.activeElement通过focusin/focusout监听见下文fullscreenElementdocument.fullscreenElementfullscreenchangepointerLockElementdocument.pointerLockElementpointerlockchangevisibilityStatedocument.visibilityStatevisibilitychange绑定配置在源码中的定义这四个属性的元数据集中定义在 binding_properties 中且都以valid_elements: [svelte:document]限定为仅可用于该特殊元素并统一标注omit_in_ssr: true// document activeElement: { valid_elements: [svelte:document], omit_in_ssr: true }, fullscreenElement: { valid_elements: [svelte:document], event: fullscreenchange, omit_in_ssr: true }, pointerLockElement: { valid_elements: [svelte:document], event: pointerlockchange, omit_in_ssr: true }, visibilityState: { valid_elements: [svelte:document], event: visibilitychange, omit_in_ssr: true }两个值得注意的点omit_in_ssr: true意味着这些绑定在服务端渲染时会被省略——服务器端没有document对象绑定只发生在客户端水合/挂载后生效与svelte:window的scrollX/scrollY不同二者是bidirectional: truedocument 的四个绑定都没有bidirectional标志与文档All are readonly的表述一致绑定只会把 DOM 上的值同步到你的变量而不会反向写入document。运行时实现监听、同步与自动清理绑定运行时的核心在 bindings/document.jsexport function bind_active_element(update) { listen(document, [focusin, focusout], (event) { if (event event.type focusout /** type {FocusEvent} */ (event).relatedTarget) { // The tests still pass if we remove this, because of JSDOM limitations, but it is necessary // to avoid temporarily resetting to document.body return; } update(document.activeElement); }); }这里有一个源码注释解释的边界处理focusout若带有relatedTarget即焦点正转移到另一个元素会被跳过以避免焦点在转移过程中被临时错误地回退到document.body导致绑定的值出现闪烁。其余属性fullscreenElement等则由通用机制根据binding_properties中的event字段订阅对应事件并在事件触发时读取document上对应属性、调用update同步到响应式变量。这些监听都依赖 listen 辅助函数export function listen(target, events, handler, call_handler_immediately true) { if (call_handler_immediately) { handler(); } for (var name of events) { target.addEventListener(name, handler); } teardown(() { for (var name of events) { target.removeEventListener(name, handler); } }); }可以归纳出三点行为保证立即同步一次call_handler_immediately默认为true挂载时会先执行一次 handler因此组件挂载后立即拿到document当前属性值自动清理通过teardown注册反注册逻辑当组件的渲染 effect 被销毁时自动removeEventListener——这与svelte:window文档中无需担心组件销毁时移除监听器的承诺一致你在svelte:document上声明的onevent监听同样享受此机制SSR 安全与svelte:window一样不需要手写typeof window ! undefined之类的存在性检查。运行期测试用例仓库中的运行时测试覆盖了真实用法可作参考document-binding-fullscreen/main.sveltescript export let fullscreen; /script svelte:document bind:fullscreenElement{fullscreen}/ div/divdocument-binding-active/main.sveltescript let active; $: console.log(active?.id || active?.nodeName || ...); /script svelte:document bind:activeElement{active} / button idoneone/button button idtwotwo/button点击两个按钮时active会随document.activeElement的变化在one、two与BODY之间同步更新。对 document 使用 Attachments除了事件与绑定svelte:document还支持 Svelte 5 的 attachments 语法{attach}将自定义附件逻辑如 use 机制风格的封装直接挂到document上。文档给出的组合示例即svelte:document onvisibilitychange{handleVisibilityChange} {attach someAttachment} /attachment 与svelte:document事件监听共存于同一顶层节点二者互不干扰attachment 的完整语法与返回值约定见 09-attach.md。与svelte:window的差异对比维度svelte:windowsvelte:document事件目标windowdocument可捕获visibilitychange等仅在 document 上触发的事件可绑定属性innerWidth、innerHeight、outerWidth、outerHeight、scrollX、scrollY、online、devicePixelRatioactiveElement、fullscreenElement、pointerLockElement、visibilityState双向绑定scrollX、scrollY可写无全部只读位置限制仅组件顶层不能在块/元素内仅组件顶层不能在块/元素内子节点不允许不允许disallow_children校验普通属性/展开不支持不支持illegal_element_attribute错误两者在 bindings.js 中成对定义且均被invalid_elements: [svelte:window, svelte:document]排除在clientWidth/offsetWidth/innerText等通用 DOM 绑定之外——即不能在svelte:document上使用这些绑定编译器会报错。总结svelte:document是接入 document 级事件的声明式入口onvisibilitychange、onfullscreenchange、onpointerlockchange等写法与组件内其他事件属性一致且监听器随组件销毁自动清理仅支持四个只读绑定activeElement、fullscreenElement、pointerLockElement、visibilityState全部omit_in_ssr只在客户端生效只能位于组件顶层不能有子节点不能携带普通属性或{...spread}展开事件处理函数会经过全局事件引用校验结合{attach}它也是把自定义附件逻辑挂到document上的标准位置。如需查看完整行为回归可浏览 tests/runtime-legacy/samples 下document-binding-*相关目录以及 tests/validator/samples 中illegal_spread_element-document、document-binding-invalid-dimensions等校验用例。【免费下载链接】svelteweb development for the rest of us项目地址: https://gitcode.com/GitHub_Trending/sv/svelte创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考