在开发 UniApp X 应用的过程中,你是否也曾在 id
、ref
、Element
、NodeRef
、context
、ComponentPublicInstance
这些“组件身份证”之间感到过困惑?它们看起来都像是用来标识组件的,但又各不相同,用法也因平台而异,稍有不慎就容易“张冠李戴”。
别担心,这篇文章将带你穿越“组件标识迷宫”,用一个你最熟悉的例子 —— <video>
视频组件,来串起这些概念的异同。读完你会发现,原来这些“身份证”,各有各的用途,而且用对了,真的会很香!
🧩 为什么需要组件标志?
在前端开发中,我们常常需要:
- 获取某个组件的引用
- 调用它的方法(比如
play()
、pause()
) - 获取或设置它的属性值
这就需要一种方式来“标记”组件,并通过这个标记找到它。于是,不同平台、不同框架就诞生了各自的“身份证系统”:id
、ref
、Element
、context
……等等。
🌐 Web 平台:HTML 原生与 Vue 的“双身份体系”
📌 原生 HTML 组件:用 id
和 document.getElementById
<video id="vid" src="uni.mp4"></video>
<script>
document.getElementById("vid").play();
// TypeScript 写法
(document.getElementById("vid") as HTMLVideoElement).play();
</script>
id
是 HTML 的“身份证”,通过document.getElementById()
获取的是一个Element
类型对象。- 如果你想要调用视频的
play()
方法,必须将其类型断言为HTMLVideoElement
。
📌 Vue 自定义组件:用 ref
和 ComponentPublicInstance
<component1 ref="c1"></component1>
this.$refs.c1.getSome();
// 或者更严谨的 TypeScript 写法
(this.$refs["c1"] as ComponentPublicInstance).getSome();
ref
是 Vue 的“身份证”,用于获取组件实例。- 调用组件方法时,需通过
ComponentPublicInstance
类型进行断言。
📝 小贴士:在 Web 平台,
ref
一般用于 Vue 自定义组件,不推荐用于原生 HTML 标签。
📱 小程序平台:两种方式,一种是官方推荐
📌 内置组件:用 id
+ uni.createXXXContext
<video id="vid" src="uni.mp4"></video>
uni.createVideoContext('vid').play();
- 小程序中推荐使用
uni.createXXXContext()
获取组件上下文对象(如VideoContext
)。 - 这种方式简洁、安全,且跨平台兼容性好。
📌 用 createSelectorQuery
+ NodeRef
获取组件上下文
uni.createSelectorQuery()
.select('.the-video-class')
.context(res => {
console.log(res.context); // 如:VideoContext
})
.exec();
- 这种方式更灵活,适合复杂布局或动态选择。
- 但要注意:
context
并非所有组件都支持,且使用起来略显繁琐。
📌 Vue 自定义组件:继续使用 ref
与 Web 平台一致,小程序中 Vue 组件仍可通过 ref
获取组件实例并调用方法。
🚀 UniApp X:融合平台,兼容并包
UniApp X 是一个多平台融合的框架,它同时支持 Web、小程序、Vue 的开发方式。因此,上述提到的这些“身份证系统”,它都支持!
但正因为如此,它也带来了更多的选择和复杂性。我们来分门别类地看看:
🧱 内置组件:Element 是基础,context 是补充
✅ Element:通用的组件操作方式
(uni.getElementById("vid") as UniVideoElement).play();
uni.getElementById<UniVideoElement>("vid")!.play();
Element
是 UniApp X 提供的基础组件类型。- 支持通用操作如
getAttribute
、setStyle
。 - 使用
uni.getElementById()
获取当前页面的元素(注意:不能获取dialogPage
页面的元素)。 - 也可以通过页面实例获取:
this.$page.getElementById()
。
✅ context:为某些组件提供专用方法(如 play()
)
uni.createVideoContext("vid")!.play();
- 类似小程序 API,为某些组件提供专属上下文对象(如
VideoContext
)。 - 更加语义化,适合调用组件内置方法。
⚠️ NodeRef:支持但功能受限
uni.createSelectorQuery().select('#vid')...
- 虽然支持
createSelectorQuery
,但无法通过.context
获取上下文对象。 - 所以在 UniApp X 中,
NodeRef
更适合布局定位,不适合获取组件方法。
✅ ref:Vue 风格的组件引用方式
(this.$refs['vid'] as UniVideoElement).play();
ref
在 UniApp X 中也可以用于内置组件。- 但通常我们更推荐它用于 Vue 自定义组件。
🎯 Vue 自定义组件:继续使用熟悉的 ref 与 ComponentPublicInstance
<component1 ref="c1"></component1>
this.$refs.c1.getSome();
(this.$refs["c1"] as ComponentPublicInstance).getSome();
- 与 Web 和小程序保持一致。
- 这是 Vue 开发者最熟悉的“身份证”方式。
🧠 总结:组件标志的“身份证”图谱
概念 | 平台 | 用途 | 是否推荐 |
---|---|---|---|
id | Web、小程序 | 原生组件唯一标识 | ✅ 推荐 |
ref | Vue | 获取组件实例 | ✅ 推荐 |
Element | UniApp X | 获取组件基础对象 | ✅ 推荐 |
context | 小程序、UniApp X | 获取组件专用上下文 | ✅ 推荐 |
NodeRef | 小程序、UniApp X | 获取组件节点引用 | ⚠️ 有限支持 |
ComponentPublicInstance | Vue | 明确组件类型后调用方法 | ✅ 推荐 |
💡 最后的小建议
- 如果你在开发一个跨平台项目,优先使用
uni.createXXXContext()
和Element
,这样兼容性最好。 - 如果你使用 Vue 组件,
ref
是最自然的选择。 - 不要轻易混用多种方式,容易造成混乱。
- TypeScript 用户记得用泛型或类型断言来提高类型安全性。
📚 结语
组件标志就像是组件的“身份证”,虽然每个平台都有自己的“身份证系统”,但只要你理解了它们的用途和区别,就能在 UniApp X 的多平台世界中游刃有余。
希望这篇文章能帮你理清思路,在开发中少踩坑、多出活。如果你觉得有帮助,别忘了点个赞、收藏、转发,让更多开发者一起告别“组件身份证焦虑”!
📢 欢迎关注我的 UniApp X 技术专栏,持续更新跨平台开发技巧与实战经验。我们下期再见!👋