跳到主要内容

事件对接 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、完整页 /embedevents=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(繁體)、enms(马来语)、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'事件类型
videoIdstring视频 ID
titlestring视频标题
watchUrlstring该视频的播放页完整地址(打开后自动播放)。⚠️ 若事件来自观看页,框内已经跳过去了,此处只作参考、不要再打开一次
{
"source": "vcms",
"type": "video:click",
"videoId": "dcfc79f8-5650-4f6f-9416-3161e33f7af6",
"title": "APB 品牌宣传片",
"watchUrl": "https://vcms-qa.acorners.com/watch/dcfc79f8-5650-4f6f-9416-3161e33f7af6"
}

more:click — 用户点了「更多」

字段类型说明
source'vcms'固定值
type'more:click'事件类型
urlstring视频中心「全部」的完整地址
{
"source": "vcms",
"type": "more:click",
"url": "https://vcms-qa.acorners.com/"
}

接入(父页面监听)

在嵌入了 iframe 的页面里加一个 message 监听,按 type 处理:

<script>
window.addEventListener('message', (e) => {
// 1) 只认 VCMS 的事件
if (!e.data || e.data.source !== 'vcms') return;

// 2)(推荐)校验来源域名,更安全
// if (e.origin !== 'https://vcms-qa.acorners.com') return;

switch (e.data.type) {
case 'video:click':
// 例:在新窗口打开播放页
window.open(e.data.watchUrl, '_blank');
// 或:埋点统计
// track('video_click', { id: e.data.videoId, title: e.data.title });
break;

case 'more:click':
// 例:跳转到视频中心
location.href = e.data.url;
break;
}
});
</script>

上面这段是给横条 / 完整页用的。若你同时嵌了观看页,请改用前文 「同一页嵌了多个组件时怎么区分」那一版,否则观看页的点击会跳两次。

怎么选模式?

  • 自己掌控点击后的行为(开新窗口、在你的 SPA 里路由、先弹个确认框)→ 用 events=1,在监听里自己处理 watchUrl / url
  • 只想记录用户点了什么、跳转交给组件 → 用 events=nav,监听里只做埋点,组件会自己跳。
  • 嵌的是观看页 → 模式仍写 events=1,但它总是自己在框内跳,你的监听只做埋点。

用户标识 (uid)

lang 一样,uid 也是地址上的参数,不通过 postMessage 传递:

<iframe src="https://vcms-qa.acorners.com/strip?platform=1&uid=a3f8c91e4b7d2065f1c8e93a4d6b0271"></iframe>

带上之后,点赞 / 不喜欢与搜索历史按这个用户记录而不是按浏览器记录。必须与 platform 同时出现才生效;不带时行为与以前完全一致。完整规则见 概览 · 可选参数 uid

uid 不需要、也不会随 postMessage 事件回传给你 —— 那个值本来就是你自己给的。


安全与注意事项

  • 过滤 source:始终先判断 e.data.source === 'vcms',页面里可能有别的 postMessage
  • ⚠️ uid 不是认证凭据:它是地址栏里的明文参数,任何人都能改。请勿用它承载登录态。 伪造它最多只能影响那个用户自己在某个视频上的点赞状态与搜索历史,但你不应把它当作身份证明。
  • 校验 e.origin(推荐):生产环境建议再加一道 e.origin === '你的VCMS门户域名',防止伪造。
  • 防盗链:你的域名需在允许 referrer 白名单内(请联系我们开通),否则视频/缩略图会 403。
  • 自动播放watchUrl 打开后会尝试自动播放;浏览器的自动播放策略可能要求静音或一次用户交互,这是浏览器层面的限制。
  • targetOrigin:组件用 '*' 发送,因此接收方务必自己校验 e.data.source(和可选的 e.origin)。

在线体验

VCMS 后台 「教学」 页底部的「事件对接」一节有一个实时模拟:嵌入一个 events=1 的组件,点「更多」或视频就能在右边实时看到收到的事件 JSON,并附有可复制的嵌入代码与监听代码。

同一节下方还有一个 观看页 的实时模拟(v1.4.1 起):点它「视频分类」里的视频,事件会出现在同一个日志里 —— 用来直观确认「同一个监听同时收两种组件」的效果,以及观看页在框内自己跳转的行为。

同页的「父页面切换语言」一节还有一个语言切换实时模拟:点语言按钮即以 postMessage 通知嵌入的组件切换语言(不重载),并附可复制的 ?lang= 嵌入代码与切换代码。