面对组件的不听话,我还是用了它…………

🧩 当 <swiper> 不听话的时候:我与 getCurrentInstance() 的灵魂对话

有时候,写代码就像在养宠物。你以为你在控制它,其实是它在戏弄你 🐶。 ------ 一个被 uni.createVideoContext() 玩坏的前端开发者。


🎬 起因:我的视频不听话

最近在用 uni-app + Vue3 做一个"仿抖音短视频"页面。 你知道的,就是那种上滑切换,下滑返回,播放、暂停全自动的效果。

我写了一个漂亮的 swiper 组件,每个 swiper-item 里面放一个 video。 切换的时候,我希望上一个视频暂停、下一个视频自动播放。听起来很合理,对吧?🤔

于是我写下了几行理所当然的伪代码:

复制代码
当滑动到下一个视频时:
    找到上一个视频
    暂停它
    找到当前视频
    播放它

理论上完美 ✅。 实际效果?❌ 上一个视频愣是还在"热情洋溢"地播放! 我滑了半天,页面成了个"多重奏"现场 🎶。


🧠 第一次怀疑人生:我的 createVideoContext 坏了吗?

我当时心想: "奇怪,我的查找视频上下文不是写对了吗?createVideoContext('video-123'),这不就行了吗?"

于是我疯狂输出日志、打印对象、console.log 全开火力 🔥。 结果发现: 👉 它根本没找到那个视频对象。

我怀疑是不是我写错了 id。 我仔细数了下:video-1video-2video-3......全都对的。 但 createVideoContext() 死活就是"找不到视频"。

我盯着控制台发呆 5 分钟,开始怀疑自己是不是生活在另一个维度 🌀。


💡 灵光一闪:难道是作用域问题?

突然我想起来一个古早的 Vue 概念------ "组件作用域"。

于是我做了个实验。 我加了个播放按钮,直接点某个视频播放。 结果------按钮点了也没反应 😭。 不是逻辑问题,而是找不到视频节点!

我这才意识到:

哦豁,这不是单纯的 Vue 页面。 我现在在玩的是 "Vue + 原生小程序 + 组件沙盒" 的三合一组合拳!🥊


🕵️ 第二次调查:swiper 的"真面目"

接着我翻了一下官方文档(是的,没事多看文档救命 🧾)。

我发现一个惊天秘密:

<swiper><swiper-item> 在 uni-app 里不是普通的 Vue 标签, 它们其实是原生平台组件,比如微信小程序原生的 swiper。

这就像你以为你在 Vue 世界里写代码, 但其实你的一部分 DOM 已经被"托运"到底层平台去渲染了 🚛。

换句话说:

css 复制代码
页面(Page)
  └── 我的Vue组件
       └── swiper(其实是原生层的组件)
            ├── swiper-item 1(一个独立作用域)
            │    └── video 1
            ├── swiper-item 2(另一个作用域)
            │    └── video 2

看到没? 这些 swiper-item 其实被"装箱"发到原生层展示去了。 你以为它们还在你的组件内部, 但实际上它们早已经搬出去单独生活 🏠。


🚨 真相浮出水面:我在错的地方找对象!

于是我终于懂了:

我在当前组件里喊:

bash 复制代码
找一下 id 为 video-1 的视频!

系统听到了,但它去错地方找了------ 它只会在"当前页面"作用域里翻找, 结果那个视频其实藏在 <swiper-item> 的"子作用域"里。 你说它能找到才怪 🤷‍♂️。


🧩 解决方案:召唤 getCurrentInstance()

这时候,我遇到了一个神秘的法术: getCurrentInstance() 🪄。

它的意思是:"获取我当前组件的实例对象"。 在 Vue3 里没有 this,所以想拿到组件上下文,就得靠它。

于是我试着这样想象:

复制代码
嘿 uni-app,
我知道你平时只在全局页面里找视频,
但我现在这个视频是在我的小组件里,
麻烦你到我的小仓库(instance)里找一下。

uni-app 很懂事地回答:"收到,老大。" 然后啪的一下,就能控制视频播放和暂停了 🎉。


🧠 延伸理解:getCurrentInstance() 就像一张"定位卡"

如果把 uni-app 比喻成一个仓库系统:

  • 整个页面是总仓库
  • 每个 Vue 组件是一个分仓库
  • 而 swiper-item 就像是一个"外包的临时仓库", 它不和主仓共享目录。

当我只写 createVideoContext('video-1'), 系统就只在"总仓库"翻找。

而我真正的货(video)在"分仓库"里。 于是------找不到。

只有当我加上 getCurrentInstance() 这张"仓库定位卡", 系统才知道该去哪儿取货 🏷️。


🧩 再理解一层:为什么 <swiper> 看起来在同一个文件,却不是同一个世界?

这部分真相更玄学 😂。

虽然我写在同一个 .vue 文件里, 但是------ uni-app 的编译器会把 <swiper-item> 的内容拆成独立的小块交给原生引擎。

所以从 Vue 的角度来看,它像这样:

makefile 复制代码
Vue: 我渲染了个 swiper 组件
原生层: 好的,我接管它,帮你展示 UI

于是你的 <video> 不再属于 Vue 自己渲染的虚拟DOM, 而是交给原生层去展示。

createVideoContext() 默认在哪找? 👉 它默认只在 Vue 页面自己能看到的那一层找。 自然找不到被"托管"的视频。


🧩 你可能会问:"那为什么不是全局实例?"

因为 Vue 设计哲学就是 ------ "各扫门前雪,不扰他人霜" ❄️。

getCurrentInstance() 只返回当前组件实例, 不会给你"所有实例"的集合。

如果 Vue 让你随便跨组件访问,那组件隔离就全废了。 这对性能、维护、安全,都是灾难级的设计。

所以,Vue 不提供"全局通行证", 而是要求你在谁家拿钥匙就只能开谁家的门 🗝️。


🔍 最终总结

我们这一场"视频播放风波"的真相其实就一句话:

不是你的代码写错了,而是你找错了层级。

<swiper><swiper-item> 虽然在同一个 .vue 文件里, 但它们运行在不同的渲染作用域。 video 节点藏在更深的一层"原生作用域"里。 只有加上 getCurrentInstance(), uni-app 才知道要到你这个组件的世界里去找那个视频 🎯。


🎁 如果 getCurrentInstance() 会说话

👨‍💻 你:我明明在这个 Vue 文件里,为什么视频不听话?!

🤖 getCurrentInstance():兄弟,你找错门了,那视频住在 swiper-item 的楼下。

👨‍💻 你:啊?那我该怎么办?

🤖 getCurrentInstance():给我一张通行证,我带你进去 😎。


🧘 最后的感悟

那一刻我突然有点感动(或者说释怀😅)。

原来 getCurrentInstance() 不只是一个API, 它其实是一种"沟通的桥梁" 🌉------ 让 Vue 世界和原生世界能互相理解。

它告诉我一个道理:

写代码也像谈恋爱------ 你以为只是一个简单的"找对象", 但其实要先确定"找的范围对不对"。💔💖


相关推荐
漂流瓶jz4 小时前
Webpack中各种devtool配置的含义与SourceMap生成逻辑
前端·javascript·webpack
这是个栗子5 小时前
【问题解决】用pnpm创建的 Vue3项目找不到 .eslintrc.js文件 及 后续的eslint配置的解决办法
javascript·vue.js·pnpm·eslint
前端架构师-老李5 小时前
React 中 useCallback 的基本使用和原理解析
前端·react.js·前端框架
木易 士心5 小时前
CSS 中 `data-status` 的使用详解
前端·css
明月与玄武5 小时前
前端缓存战争:回车与刷新按钮的终极对决!
前端·缓存·回车 vs 点击刷新
花姐夫Jun5 小时前
基于Vue+Python+Orange Pi Zero3的完整视频监控方案
vue.js·python·音视频
牧马少女5 小时前
css 画一个圆角渐变色边框
前端·css
zy happy6 小时前
RuoyiApp 在vuex,state存储nickname vue2
前端·javascript·小程序·uni-app·vue·ruoyi
小雨青年6 小时前
Cursor 项目实战:AI播客策划助手(二)—— 多轮交互打磨播客文案的技术实现与实践
前端·人工智能·状态模式·交互
Nan_Shu_6146 小时前
学习:JavaScript(5)
开发语言·javascript·学习