16 · `custom-media-element`:属性拦截与转发

如何处理动态语言(Python / JS)的“隐形”调用链? 本文揭示动态语言(Python/JS)中静态AST解析导致调用链“断链”的核心问题,提出通过运行时追踪补全图谱的解决方案。基于Code-Graph-RAG的cgr trace机制,分别利用pytest插件与V8 Profiler捕获真实调用路径,将动态边合并至静态图谱,并在权重体系中提升动态边优先级。实践表明,该方法可显著提升图谱覆盖率,实现“结构+行为”双视角理解代码,为MCP与Rerank系统提供可靠支持。 阅读详情

上一篇讲了 HTMLMediaElementHost 的主机-组件模型。但 host 是个普通 JS 对象,不是 Web Component。这篇讲 CustomMediaElement——一个类工厂,把 host 包装成自定义元素,让它能像 <video> 一样用 HTML 属性声明式控制。核心是两层属性转发:HTML 属性 → host 属性 → 真实媒体元素。

它是什么:一个混入工厂

packages/media/src/dom/custom-media-element/custom-media-element.ts:105-108:

export function CustomMediaElement(tag, MediaHost) {
  // ...
}

它接收一个 HTML 标签名(如 'video')和一个 MediaHost 构造器(如 HTMLVideoElementHost),返回一个 CustomMedia 自定义元素类。这个类桥接自定义元素 API 和 media host。

比如 <mux-video> 元素就是 CustomMediaElement('video', HlsJsMedia) 的产物——用户写 <mux-video src="...">,它内部转发到 host 和真实 <video>。

内部元素在开放的 Shadow DOM

构造函数(L234-244)会 attachShadow({ mode: 'open' }),模板(getVideoTemplateHTML L26-56)渲染一个 <slot name="media"><video></video></slot>。

get target()(L270-277)解析内部元素,优先级:slotted 子元素(:scope > [slot=media])> 宿主中的 <tag> > shadow root 中的 <tag>。

为什么用开放 Shadow DOM?因为 slotted 模式让外部 CSS 和 light DOM 子元素(<track>/<source>)仍然能正常工作,同时把内部媒体元素隔离。

两层转发策略

属性转发是这篇的重点,有两套机制。

第一层:Host 原型遍历(L152-203)

static #define 内部遍历 MediaHost.prototype 的原型链,为每个属性在 CustomMedia.prototype 上装代理:

方法是(L172-175):

config.value = function(...args) { return this.#mediaHost[prop](...args); };

getter(L176-179):

config.get = function() { return this.#mediaHost[prop]; };

setter 分两种:

  • 如果属性的 kebab-case 名在 observedAttributes 里(L182-184),setter 通过 toggleAttribute/setAttribute(L186-192)——设置 JS 属性会触及 HTML 属性,走 attributeChangedCallback 路由。
  • 否则直接写 this.#mediaHost[prop] = val(L194-196)。

这个分支很关键:有些属性要走 HTML 属性(因为属性变化会触发浏览器行为),有些直接写 host。比如 src 走属性(浏览器会触发 loadstart),volume 可以直接写。

第二层:显式属性循环(L205-223)

static properties(L119-135)声明了属性到属性的映射,包括 autoplay、controls、loop、muted(属性 muted)、preload、src、streamType(属性 stream-type)等。每个条目指定 { type: Boolean|String, attribute?, empty? }。

对那些没被第一层遍历连接的属性,第二层定义直接读/写元素属性的 getter/setter:布尔用 hasAttribute,字符串用 getAttribute。

两层为什么要分开

我读的时候琢磨了一下。第一层(原型遍历)是「自动发现」——host 有啥就代理啥,省得手写。但有些属性的 HTML 名和 JS 名不一致(defaultMuted 对应属性 muted、playsInline 对应 playsinline),自动遍历搞不定,需要第二层显式声明。

两层配合:自动的尽量自动,特殊的显式处理。这是务实的工程取舍。

attributeChangedCallback:属性 → 属性

L322-353 处理 HTML 属性变化:

  1. 如果 mediaHostAttrToProp 映射到 host 属性(L323-337),按 typeof this.#mediaHost[prop] 做类型转换(布尔/数字/字符串),写入 host——最终流向附加元素。
  2. 如果属性没被 CustomMedia 观察到但被子类观察(L339-344),提前 return 让子类处理。
  3. 否则对同步目标(syncTargetAttributes = tag !== 'iframe',L346-352),镜像到内部元素:null → removeAttribute,否则 setAttribute。

注意 syncTargetAttributes——iframe/embed(Vimeo 那种)驱动外部播放器,属性不镜像到内部。

子元素同步:<track> 和 <source>

构造函数设了个 MutationObserver(L244 附近)监听 <track>/<source> 子元素,slotchange 时重新附加 + 重新同步。

#syncMediaChildren(L355-385)把 slotted 的 <track>/<source> 克隆到内部原生元素并保持同步。iframe 排除在外。

#enableDefaultTrack(L403-415)为 chapters/metadata 轨道启用 default——因为浏览器不会对 JS 添加的轨道自动启用。这是个浏览器行为的补丁。

事件桥

addEventListener(L296-306)把监听器类型转发到 #mediaHost。#bridgeEvent(L316-320)重建并重新分发事件,除非它已经组合(composed 事件会自动冒泡穿过 shadow 边界,不用桥接)。

这和 06 篇讲的 resolveEventTarget(composedPath 穿透 shadow)是互补的——这里是从内向外转发。

销毁保护:queueMicrotask 检查 isConnected

disconnectedCallback(L287-294)和 element 包的 DestroyMixin(10 篇)思路类似:遵 keep-alive 属性,排 queueMicrotask 检查 isConnected——同步重新挂载(移除后立即插回)不会销毁 host。

不过这里用的是单次 queueMicrotask(不是 DestroyMixin 的双重 rAF)。因为这里保护的是「同步重新挂载」,微任务足够;DestroyMixin 的双重 rAF 保护的是「跨帧 DOM 重组」,更激进。

小结

CustomMediaElement 把 host 包装成可声明式使用的 Web Component。核心是两层属性转发:

  1. 原型遍历自动代理——host 有啥就代理啥。
  2. 显式属性声明——处理名字不一致的特殊属性。
  3. attributeChangedCallback 类型转换——字符串属性转成正确类型写 host。
  4. 子元素克隆同步——<track>/<source> 进 shadow。
  5. 事件桥——非 composed 事件手动转发。

这层让 <mux-video>、<hlsjs-video> 这些自定义元素能像原生 <video> 一样用。下一篇讲这些引擎适配器的全景。

【Claude Code · VibeCoding】11|需求梳理:云枢智学 / 学员平台 第三章 · 项目实战以「云枢智学」学员平台为例,把业务目标拆成可执行的需求条目。 阅读详情

相关推荐

SpringBoot+Vue+MySQL 高校学科竞赛平台 完整可运行版(源码+文档)

本项目基于SpringBoot+Vue+MySQL构建高校学科竞赛管理平台,覆盖学生、教师、领队教师、管理员四大角色,实现竞赛发布、报名、刷题、评分、公示等全流程闭环管理。系统架构清晰,技术主流,配套完整源码、数据库脚本、万字论文、开题报告、答辩PPT及部署文档,支持一键运行,适用于毕业设计、课程设计及院系二次开发,真正实现“开箱即用”。

招风的黑耳优快云 18

Web 版翻译者资料库

本项目是桌面版《翻译者资料库》的 Web 移植版,基于 Spring Boot 3.3、Thymeleaf、Bootstrap 5.3 与 MySQL 8.0 构建。它面向翻译写作提供资料、词汇、句库、文本工具、对照制作、查找、备份恢复及旧库迁移等功能,完整继承桌面版核心业务规则,支持一键启动与离线访问。

howard2005的专栏 140

SpringBoot+Vue 社区医院信息平台 完整源码+全套文档 开箱即用

本文介绍一套基于SpringBoot+Vue+MySQL的社区医院信息平台,覆盖患者、医生、护士、药品管理员、管理员五大角色,实现从挂号就诊、开方注射、取药结算到数据统计的全流程闭环管理。系统采用成熟技术栈,架构清晰,权限分明,配套完整源码、数据库脚本、万字论文、答辩PPT及部署文档,可直接用于毕业设计或基层医疗信息化落地,助力高效开发与快速交付。

招风的黑耳优快云 282

V8 机制、手写核心函数与 TypeScript 类型体操

或固定初始化(如数组先定长、对象先给全字段)保持类型与形状稳定;这些都比"换框架"更基础。只能处理纯数据(丢函数、Date、RegExp、循环引用报错)。生产级深拷贝要处理:原始值短路、循环引用、V8(Chrome / Node 的 JS 引擎)不是"解释一行跑一行"那么简单,它用。图:V8 执行流程——解释执行 + 热点优化,优化失败会 Deopt 回退。JS 内存自动管理,但"自动"不等于"不会漏"。是"固定间隔最多执行一次"。手写 Promise 是"懂异步"的试金石。是"停下后才执行最后一次",

qq_38468358的博客 346

风控要略-互联网业务反欺诈之路(一)

当前中国互联网安全产业答题可以分为基础安全和业务安全两个领域。从互联网诞生至2014年,互联网安全行业关注的热点基本都聚焦在网络安全、系统安全和应用安全这个三大基础安全领域上,“DDOS“(分布式拒绝服务攻击)1、“漏洞“、“拖库“2和“挂马“3等大家耳熟能详的术语也是从这些领域中衍生出来的。2014年前后,随着互联网业务的爆炸式发展,黑产团伙开始从“攻击渗透系统“的传统套路进化到“利用业务风控确实进行大规模牟利“的模式,并且逐渐形成规模庞大、分工明确的黑色产业链。

Despacito1006的博客 1012

Halcon频域滤波实战:5分钟搞定傅里叶变换与功率谱分析(附完整代码)

本文提供Halcon频域滤波的实战指南,重点讲解如何利用傅里叶变换与功率谱分析快速解决图像处理难题。通过核心算子fft_image和power_real,演示了从空间域转换到频域、分析功率谱以定位周期性噪声,并构造滤波器进行精准去除的完整流程,附有可直接运行的代码示例。

docker8compose的博客 215

副队长BootStrap5探究(2)--按钮与按钮组

本文系统讲解Bootstrap 5按钮组件的使用与底层原理。通过CDN引入框架,掌握btn基础类及primary、success等主题色应用,学习轮廓按钮(btn-outline-*)、尺寸控制(btn-lg/sm)、块级布局(d-block)和禁用状态(disabled)等实用功能。结合源码解析,深入理解其基于CSS的圆角、过渡动画、伪类交互实现机制,实现“快速上手+原理掌握”的双重目标,助力前端技能进阶。

编程副队长 517

华三模拟器实战:IPSec VPN穿越NAT的完整配置与调试(附常见问题排查)

本文详细解析了华三模拟器中IPSec VPN穿越NAT的完整配置与调试方法,包括基础环境准备、分步配置、ACL协调策略及高级故障排查。通过实战案例和关键参数解析,帮助网络工程师解决IPSec与NAT协同工作的典型问题,提升企业网络安全性。

weixin_33724046的博客 460

React 性能:memo / useMemo / useCallback

讲清 memo/useMemo/useCallback 的配合与边界,先测量再优化,避开常见过早优化。

JudithHuang的博客 325

保姆级教程:用TIA Portal V17给S7-1200 PLC和HMI做个联调仿真(附抢答器完整项目包)

本文提供了一份详细的TIA Portal V17教程,指导如何实现S7-1200 PLC与HMI的联合仿真开发。通过抢答器项目实例,涵盖从环境搭建、PLC编程到HMI设计的全流程,帮助工程师高效完成工业自动化系统的虚拟调试,显著提升开发效率。

weixin_30417487的博客 624

给新人的储能系统入门图解:从电芯到EMS,一张图看懂BESS里那些‘黑话’

本文通过视觉化拆解储能系统,从电芯到EMS详细解析BESS中的关键组件和行业术语。涵盖电芯参数、模组组装、PCS功能、BMS与EMS分工,以及SOC、DOD等关键运维参数,帮助新人快速理解储能系统的核心技术和应用场景。

weixin_42522964的博客 594

DSH (DeepSeek Harness) Windows 升级安装指南20261107

注意:如果在普通窗口执行 nvm 提示找不到命令,或执行 nvm use 提示 Access is denied,请务必关闭当前窗口,重新打开一个管理员CMD 执行上述完整路径命令。找到 .credentials.yaml,将其重命名为 .credentials.yaml.bak(备份并使其失效)。Node.js Storage Location:可改到非系统盘(如 D:\dev\nvm,避免路径含空格或中文)。打开文件资源管理器,进入 C:\Users<你的用户名>.dsh\。

fengye207161的博客 193

杰理的蓝牙芯片的key是什么?以及该如何添加key?杰理key文件原理

很多的工程师,在开发杰理蓝牙芯片的第一步就会有一个很深的疑惑,关于key的 1、什么是key文件? 2、Key文件是如何产生的? 3、为什么需要他key文件? 4、如何添加key文件? 5、以及实际开发中的一些报错该如何处理?

qyvhome的博客 4095

SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在

# SpringBoot「衣依」服装销售平台:144个Java文件180个接口,从挑衣服到收货评价整条链路都在 > 这是一套基于 Spring Boot 的服装销售平台源码,配套 `db.sql` 建表脚本,业务覆盖商品展示、购物车、订单流转、收货地址、订单评价、商品评论、在线客服、轮播图和资讯。形态是**前后台双端**:前台是顾客逛的商城,后台是管理员管的控制台。本文带你看清里面有什么、怎么跑

面朝大海 226

【Azure 架构师学习笔记】- Azure Private Endpoint

公有云的其中一个特点是默认允许公网访问, 这就对企业环境带来风险,也是很多年前企业对公有云抵触的其中一个原因,现在这类问题已经很少,因为有了很多技术来确保云上的资源被安全地访问。其中Private endpoint(PE)就起到了很重要的作用。云上的某个资源如VM会创建在特定的网络(VNet/Subnet)上, 而其他如Storage Account , Azure SQL等PaaS服务则没有。如果你需要用VM 来访问这些PaaS资源,VM 就会通过资源的公网IP 来访问。

MVP黄钊吉(發糞塗牆) 1788

AI测试干货:Claude Code Skill 从入门到精通

本文介绍了Claude Code Skill功能如何解决AI重复工作问题。传统提示词方式需要人工复制粘贴,而Skill功能通过建立AI工作记忆库实现智能触发和分层加载。Skill包含工作指令、文档和资源,能自动执行任务。文章以API测试用例生成为例,展示了Skill的创建流程和结构化设计,包括测试框架、覆盖场景和输出格式,显著提升测试工程师的工作效率。

blues_C的博客 2439

微信小程序-wxs

在微信开发者工具中右键创建.wxs后缀的文件。每个.wxs文件也是一个独立模块,同样使用导出内容。示例(文件return d;FOO: foo,bar: bar(外联定义参考官方文档)

dreams_dream的博客 342

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

使用echarts模拟甘特图

项目中需按时间段展示不同颜色的数据,通过解析时长并统计各类型总时长,结合预设颜色映射表(含自定义与默认色),动态生成ECharts图表。利用sumByTypeName聚合数据,为每类分配对应颜色,实现图例与柱状图的精准匹配,确保多时段、多类型数据可视化清晰准确。

uuai 28

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

设计模式(unity游戏研发版)

当你使用图形用户界面类时通常会遇到一个问题。比如,你创建了自定义按钮类并允许客户端在按钮中注入自定义代码,这样当用户按下按钮时就会触发这些代码。观察者模式允许任何实现了订阅者接口的对象订阅发布者对象的事件通知。你可在按钮中添加订阅机制,允许客户端通过自定义订阅类注入自定义代码。在Unity中,这就像UnityEvent在Inspector中绑定多个回调。

m0_63330263的博客 90

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

【技术专题】JavaScript 网页技术 - JavaScript 流程控制

小锋老师推出《一天学会JavaScript(无废话版)》视频教程,涵盖基础语法、流程控制、函数、数组对象、DOM操作及ES6新特性。内容精炼,配套课件与源码打包下载,助力快速入门。重点讲解if/else、switch、for/while循环、for...of/in遍历及break/continue使用场景,并通过成绩判断实例演示实际应用。适合零基础学习者高效掌握核心技能。

java1234的博客 162

基于 FastAPI+LangChain+LangGraph+Agent+Vue3+MySQL 的房产数据采集与房价预测分析平台

本文介绍一个完整的「房产数据采集+AI房价预测」全栈项目,涵盖FastAPI异步后端、LangGraph Agent智能问答、爬虫采集、机器学习预测与Vue3前端,实现从数据采集到AI交互的闭环。项目融合多技术栈,具备真实业务场景与生产级设计(如降级策略、流式输出、多模型对比),兼具简历亮点与答辩演示优势,可系统性提升工程能力,并附高频面试题解析,是理想的技术综合实践项目。

深耕开发,专注编程实战。分享源码解析、项目搭建、问题排查笔记,沉淀技术,持续更新。 229

货运APP、货运小程序开发:网络货运平台与同城配送搬家系统实战

本文介绍一套完整的货运平台系统,涵盖货运APP、小程序、网络货运、同城配送、搬家预约等场景,基于SpringBoot+MyBatisPlus+MySQL技术栈,采用uni-app实现多端统一开发,配套TMS运输管理与物流管理系统,支持下单、派单、运输、结算全流程,适用于货运搬家、物流搬运与配送业务,可作为物流软件及TMS系统的参考实现。

juzige03的博客 218

Vue3 低代码移动表单设计器实战(二):缩放画布下的拖拽系统与树状级联数据结构

本文深入剖析Vue3低代码表单设计器在缩放画布下的拖拽失效问题,揭示SortableJS在CSS Transform下坐标崩溃的数学根源。通过自研独立视觉克隆壳层与逆向几何补偿算法,实现精准拖拽;采用扁平数据存储+运行时树状计算结构,解决级联依赖与深克隆难题,确保逻辑一致性与性能优化,为复杂低代码系统提供可复用的工程范式。

NanChen的博客 341

LangGraph == 循环结构的实现

这是静态约束,不会参与运行时校验。主要作用是提升代码可读性、通过静态类型检查,同时帮助 LangGraph。也就是说,是否继续重试,在当前实现中主要由大模型决定,而不是由程序逻辑强制保证。因此,如果模型在多次工具调用失败后选择停止重试并生成最终回答,运行图不会阻止它。函数,也不再需要调用 add_conditional_edges()只要大模型持续返回工具调用,流程就会不断回到 llm_node。的缩写,即“推理 + 行动”架构。,运行时只负责判断具体走哪一条路径。

每天都要努力学习哦~~ 347

Vue Router

介绍vue-router的基本使用以及核心概念

k_5412528的博客 154

Vue 前端开发 AI 对话页面:流式消息渲染、文件上传

关键点是不能手动设置 Content-Type 为 multipart/form-data,必须由浏览器自动生成带有 boundary 的请求头,否则后端无法解析。思路:将对象序列化为 JSON 字符串,作为 FormData 的一个普通字段(如 formData.append(‘payload’, JSON.stringify(data))),后端接收该字段后再反序列化。若上传大文件(>10MB),需实现独立的分片上传接口,在提交对话前先获取文件 id 或 url,再随文本发送引用。移除输入框的禁用态;

2402_85729970的博客 388
上一篇: videojs v10 源代码系列解读:15 · `HTMLMediaElementHost`:主机-组件模型
下一篇: 17 · 引擎适配器全景:HLS/DASH/Vimeo/Mux/Cast
逻辑玩家
博客等级 码龄19年 75粉丝 108原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值