事件对接 API (postMessage)
当 VCMS 组件被 iframe 嵌入到你的平台时,组件可以把用户的交互(点「更多」、点视频)通过浏览器原生的 window.postMessage 抛给父页面,由你的平台决定怎么处理。
跨域安全:iframe 与父页面不同源也能通信,这是 postMessage 的标准用法。
两种模式
在嵌入 URL 上加 events 参数来启用:
| 模式 | URL 参数 | 行为 |
|---|---|---|
| 只发事件 | ?events=1 | 组件不跳转,只把事件抛给父页面。你的平台自己处理(开新窗口播放、走自家路由、弹窗等)。 |
| 跳转 + 发事件 | ?events=nav | 组件自己跳转到门户(整页),同时发事件给你(用于埋点/统计)。 |
| 不启用 | (不加 events) | 默认行为:组件用 target="_top" 自己跳转,不发事件。 |
events=nav会在发出事件后约 120ms 再跳转,确保你的监听函数(如埋点)先执行。
嵌入示例
<!-- 只发事件:你的平台全权处理交互 -->
<iframe src="https://vcms-qa.acorners.com/strip?platform=1&events=1"
width="100%" height="300" frameborder="0" scrolling="no"
allow="autoplay;encrypted-media;picture-in-picture"></iframe>
<!-- 跳转 + 发事件:组件自己跳门户,你只做埋点 -->
<iframe src="https://vcms-qa.acorners.com/strip?platform=1&events=nav"
width="100%" height="300" frameborder="0" scrolling="no"
allow="autoplay;encrypted-media;picture-in-picture"></iframe>
events 参数对横条 /strip、完整页 /embed、以及 观看页 /watch/<视频ID>?full=1(v1.4.1 起)都生效。
观看页也是事件源(v1.4.1 起)
嵌入完整观看页时,页面下方「视频分类」里的视频卡片和「更多视频」同样会发事件:
<div style="position:relative;width:100%;padding-top:56.25%">
<iframe id="vcms-watch"
src="https://vcms-qa.acorners.com/watch/{视频ID}?full=1&platform=1&events=1"
style="position:absolute;inset:0;width:100%;height:100%"
frameborder="0" allow="autoplay;encrypted-media;picture-in-picture"
allowfullscreen></iframe>
</div>
⚠️ 与横条/完整页的关键差异
观看页会自己在 iframe 内部完成跳转。 点一个分类里的视频,框 内直接换成那个视频继续播放, 你的页面不动。
也就是说,观看页发来的事件是**「通知」而不是「请你跳转」。如果照抄下面那段标准监听
(window.open(e.data.watchUrl)),点一次会跳两次** —— 框内换了视频,你的页面又开了一个新标签页。
| 组件 | 点击后 | 你该做什么 |
|---|---|---|
横条 /strip、完整页 /embed | events=1 不跳;events=nav 跳你的顶层窗口 | 按模式处理 watchUrl / url |
观看页 /watch | 总是在 iframe 内部跳转 | 只做埋点,不要再跳一次 |
同一页嵌了多个组件时怎么区分
事件负载里没有「哪个组件发的」这个字段,也不需要 —— 你本来就持有每个 iframe 的引用,
MessageEvent.source 就是发送方的 window:
<script>
const watchFrame = document.getElementById('vcms-watch');
window.addEventListener('message', (e) => {
if (!e.data || e.data.source !== 'vcms') return;
if (watchFrame && e.source === watchFrame.contentWindow) {
// 观看页:它已经在框内跳好了,这里只统计
// 换成你自己的埋点调用:
console.log('vcms', e.data.type, e.data);
return;
}
// 横条 / 完整页:按你选的模式处理
if (e.data.type === 'video:click') window.open(e.data.watchUrl, '_blank');
if (e.data.type === 'more:click') location.href = e.data.url;
});
</script>
这个办法嵌几个组件都适用,不依赖我们在负载里加字段。
两个行为细节
- 连续点击都会发事件。 观看页在框内跳转时会把
events参数一并带到下一个视频,所以你不会 出现「第一次收到、之后就没了」。 - 点「更多视频」后事件会停。 它会离开观看页、在框内跳到视频中心首页
/,而首页不是事件源 (/embed才是)。这是当前的设计取舍,不是故障 —— 若你需要那之后继续收事件,请联系我们。
语言切换 (i18n)
组件支持 7 种语言:zh-Hans(简体)、zh-Hant(繁體)、en、ms(马来语)、th(泰语)、id(印尼语)、vi(越南语)。界面文案与视频内容(标题、简介、分类名、品牌名,若后台已配置对应语言)都会随之切换;未配置翻译的语言回退到简体。
① 初始语言 —— URL 参数 lang
<iframe src="https://vcms-qa.acorners.com/strip?platform=1&lang=en"></iframe>
② 运行时切换 —— 父页面 postMessage(不重载 iframe)
当你的平台切换语言时,向 iframe 发送一条 vcms-host 消息,组件会即时切换界面并重新拉取该语言的内容,无需重载 iframe:
const frame = document.querySelector('iframe');
frame.contentWindow.postMessage(
{ source: 'vcms-host', type: 'setLang', lang: 'th' },
'*',
);
| 字段 | 值 |
|---|---|
source | 固定 'vcms-host'(区别于组件发给你的 'vcms') |
type | 'setLang' |
lang | 上述 7 个语言码之一 |
消息格式
每个事件都是一个对象,通过 window.parent.postMessage(payload, '*') 发出。所有事件都带 source: 'vcms',请用它过滤,避免和页面里其它 message 混淆。
interface VcmsEvent {
source: 'vcms';
type: 'video:click' | 'more:click';
// 其余字段随 type 不同,见下表
[key: string]: unknown;
}
事件清单
video:click — 用户点了某个视频
| 字段 | 类型 | 说明 |
|---|---|---|
source | 'vcms' | 固定值 |
type | 'video:click' | 事件类型 |
videoId | string | 视频 ID |
title | string | 视频标题 |
watchUrl | string |