当你需要根据业务诉求微调 RoomKit 的界面和交互时,可以通过以下三类能力完成:
添加自定义按钮,例如录制、答题器、白板入口、实时数据面板。
隐藏或恢复 SDK 内置按钮,裁剪默认界面。
在用户点击内置按钮后、底层操作执行前插入权限校验或二次确认。

前置条件
安装包:
@tencentcloud/roomkit-web-vue3最低版本:
>=5.4.3框架依赖:Vue 3+
能力概览
conference.setWidgetVisible():裁剪默认界面。只控制内置按钮是否显示,不限制底层功能是否可被代码调用。conference.registerWidget():增加业务入口。在工具栏新增自定义按钮,不接管内置按钮。conference.onWill():点击前做校验。只拦截内置 UI 按钮点击,不拦截主动调用的底层接口。需求 | 使用 API | 说明 |
增加业务入口 | conference.registerWidget() | 在工具栏中新增一个自定义按钮。 |
裁剪默认界面 | conference.setWidgetVisible() | 控制内置按钮是否显示。 |
点击前做校验 | conference.onWill() | 拦截内置按钮的点击操作。 |
快速开始
下面示例演示一个完整的界面微调场景:
隐藏邀请按钮。
增加一个答题器按钮。
点击开启摄像头前弹出确认框。
分别对应
setWidgetVisible()、registerWidget() 和 onWill() 三类能力。注意:
import {conference,BuiltinWidget,InterceptorAction,RoomEvent,} from '@tencentcloud/roomkit-web-vue3';import QuizPanel from './QuizPanel.vue';async function startMeeting() {await conference.login({sdkAppId: 12345678,userId: 'your-user-id',userSig: 'your-user-sig',});// 建议在 start() / join() 前完成所有界面微调,避免按钮闪烁或漏拦截conference.setWidgetVisible({[BuiltinWidget.InviteWidget]: false,});const cleanups: Array<() => void> = [];cleanups.push(conference.registerWidget({id: 'quiz',zone: 'bottom-right',icon: '📝',label: '答题器',panel: {title: '答题器',component: QuizPanel,},}),);cleanups.push(conference.onWill(InterceptorAction.OpenCamera, async (action, proceed, abort) => {if (window.confirm('确认开启摄像头?')) {proceed();} else {abort();}}),);const cleanup = () => {cleanups.forEach(fn => fn());cleanups.length = 0;conference.off(RoomEvent.ROOM_LEAVE, cleanup);conference.off(RoomEvent.ROOM_DISMISS, cleanup);};// 两个事件都要监听:// - ROOM_LEAVE:当前用户主动离开// - ROOM_DISMISS:主持人解散房间(参会者走此事件)conference.on(RoomEvent.ROOM_LEAVE, cleanup);conference.on(RoomEvent.ROOM_DISMISS, cleanup);const roomId = Date.now().toString();await conference.start({ roomId });}
显示/隐藏按钮
默认情况下,所有内置 Widget 在未调用
setWidgetVisible 时,均为显示状态。只需要对需要隐藏的按钮进行配置即可。Webinar 模式下由 RoomKit 根据房间类型和角色自动控制的 Widget 除外。
场景:隐藏内置按钮
import { conference, BuiltinWidget } from '@tencentcloud/roomkit-web-vue3';conference.setWidgetVisible({[BuiltinWidget.InviteWidget]: false,[BuiltinWidget.RoomChatWidget]: false,});
注意事项
建议在
conference.login() 完成之后、conference.join() / conference.start() 之前调用,避免按钮闪烁。setWidgetVisible() 只控制按钮是否显示,不会锁定功能本身,如果你的业务代码直接调用 SDK 底层接口,对应功能仍然会执行。setWidgetVisible() 没有注销函数;如果不同房间有不同显隐策略,请在下一次进房前显式重置。添加自定义按钮
调用
registerWidget 会返回一个注销函数,调用后可立即从工具栏移除该按钮。
场景一:状态切换按钮(支持响应式)
icon 和 label 支持函数形式,函数内部的响应式变量变化时按钮状态会自动更新:import { ref } from 'vue';import { conference } from '@tencentcloud/roomkit-web-vue3';const isRecording = ref(false);conference.registerWidget({id: 'recorder',zone: 'bottom-center',icon: () => isRecording.value ? '⏹' : '⏺',label: () => isRecording.value ? '停止录制' : '开始录制',onClick: async () => {try {if (isRecording.value) {await stopRecording();} else {await startRecording();}isRecording.value = !isRecording.value;} catch (e) {console.error('录制操作失败:', e);}},});
场景二:点击后弹出侧边面板
配置
panel 后,点击按钮会自动展开或收起侧边面板(与“聊天”“成员”等内置面板互斥,同时只能展开一个)。import { conference } from '@tencentcloud/roomkit-web-vue3';import QuizPanel from './QuizPanel.vue';conference.registerWidget({id: 'quiz',zone: 'bottom-right',icon: '📝',label: '随堂测试',panel: {title: '随堂测试',component: QuizPanel,props: { courseId: 'xxx' },},});
场景三:使用自定义组件
如果内置的图标+文字样式不能满足需求,可以使用传入
component 完全自定义触发器。import { conference } from '@tencentcloud/roomkit-web-vue3';import MyCustomTrigger from './MyCustomTrigger.vue';import MyPanel from './MyPanel.vue';conference.registerWidget({id: 'custom-trigger',zone: 'bottom-right',component: MyCustomTrigger,panel: {title: '数据面板',component: MyPanel,},});
MyCustomTrigger.vue 可通过 togglePanel 控制面板展开和收起:<script setup lang="ts">defineProps<{ togglePanel?: () => void }>();</script><template><button @click="togglePanel?.()">打开面板</button></template>
拦截内置按钮操作
适合在用户点击 SDK 内置按钮时,在底层操作真正执行之前插入你的业务逻辑,例如:
点击摄像头按钮前弹窗确认。
点击屏幕共享按钮前请求服务端校验权限。
点击麦克风按钮前显示自定义提示。

场景一:二次确认
import { conference, InterceptorAction } from '@tencentcloud/roomkit-web-vue3';conference.onWill(InterceptorAction.OpenCamera, async (action, proceed, abort) => {if (window.confirm('确认开启摄像头?')) {proceed();} else {abort();}});
场景二:异步权限校验
import { conference, InterceptorAction } from '@tencentcloud/roomkit-web-vue3';conference.onWill(InterceptorAction.StartScreenShare, async (action, proceed, abort) => {try {const hasPermission = await checkScreenSharePermission();if (hasPermission) {proceed();} else {alert('当前会议不允许屏幕共享');abort();}} catch (e) {console.error('权限校验异常:', e);abort();}});
注意事项
onWill
proceed() / abort() 必须二选一调用:漏掉会导致操作链静默终止。建议在
start() / join() 前注册:这样不会遗漏用户进房瞬间的操作。生命周期管理:务必同时监听
RoomEvent.ROOM_LEAVE 和 RoomEvent.ROOM_DISMISS 并调用注销函数;如果事件监听本身支持解绑,也应一并清理。隐藏 UI 不等于拦截操作:
onWill() 只拦截内置按钮点击路径,不能拦截底层接口调用。常见问题
按钮注册了但不显示?
最常见原因是没有传
zone,或传入的 zone 与当前设备类型不匹配。PC 和 H5 可分别指定不同区域,例如:zone: { pc: 'bottom-center', h5: 'top-right' }
多次进出会议后,自定义按钮或拦截器重复生效?
通常是离会时没有调用注销函数。请统一收集
registerWidget() 和 onWill() 返回的注销函数,并在 RoomEvent.ROOM_LEAVE 和 RoomEvent.ROOM_DISMISS 中同时清理。隐藏了按钮,为什么对应功能还能被触发?
这是预期行为。
setWidgetVisible() 只负责控制 UI,不限制功能本身。如果你的业务代码直接调用 SDK 底层接口,功能仍然会执行。如果还需要在点击前做权限判断或确认,请使用 onWill()。setWidgetVisible() 可以在会中动态调用吗?
可以,调用后按钮显示状态会立即更新。如果你的应用会复用同一个
conference 实例,请注意在下次进房前按需重置。点击按钮后功能一直没有响应?
通常是某个
handler 分支没有调用 proceed() 或 abort(),导致操作链静默终止。请检查所有 if / else / catch 分支。onWill() 能拦截我自己代码里调用的底层接口吗?
不能。
onWill() 只拦截 SDK 内置 UI 按钮的点击路径;如果你在业务代码里直接调用底层接口,需要自行补充权限控制。自定义触发器如何控制面板展开或收起?
配置了
panel 后,SDK 会自动向自定义触发器注入 togglePanel 函数。在组件中通过 defineProps<{ togglePanel?: () => void }>() 接收后,调用 togglePanel() 即可。