uni-app x 组件选择器 uni-createSelectorQuery 插件源码解析与实战指南

发布时间:2026/9/20 14:43:41
uni-app x 组件选择器 uni-createSelectorQuery 插件源码解析与实战指南 示例工程前端移动开发跨平台【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址https://gitcode.com/gh_mirrors/un/uni-app点击查看免费下载uni-createSelectorQuery 是 uni-app / uni-app x 中一个以 UTS 插件uni_modules形式实现的组件选择器扩展模块用于在页面中通过选择器获取节点布局信息、滚动位置、节点属性、样式值乃至 Context 与 Node 实例。本文以该插件的 readme.md 为主体结合 interface.uts、Android 与鸿蒙平台实现源码以及仓库内示例页面讲解其 API 契约、跨端实现原理、典型调用方式与平台兼容性帮助读者掌握uni.createSelectorQuery在 uni-app x 中的完整使用与扩展方法。一、插件是什么uni-createSelectorQuery 是一枚标准 uni_modules 格式的 UTS 插件其核心职责是实现组件选择器Selector Query功能让开发者可以像在微信小程序中一样通过uni.createSelectorQuery()链式调用select/selectAll/selectViewport等 API异步获取页面节点的布局位置、尺寸、滚动偏移、dataset、指定属性与计算样式等运行时信息。插件元信息位于 package.json其中明确了dcloudext.type为uts即这是一个 UTS 类型插件uni_modules.uni-ext-api中声明挂载了uni.createSelectorQuery扩展 API并在 Androidkotlin、iOSswift、鸿蒙arkts、H5js平台均标记为false表示该 API 不以内置原生实现接入而是由 UTS 源码直接编译到各端uni_modules.platforms声明了 Vue2/Vue3、AppAndroid/iOS、H5 移动端与 PC 端、各小程序平台以及快应用的支持范围engines.HBuilderX要求^3.6.8及以上版本。从目录结构看插件实现被划分为三部分| 目录/文件 | 目标平台 | 实现语言 | 作用描述 | | -- | -- | -- | -- | |utssdk/interface.uts| 多平台共用 | UTS | 声明SelectorQuery、NodesRef、NodeInfo、NodeField等公共类型契约 | |utssdk/app-android/index.uts| Android | UTS |SelectorQuery/NodesRef的 Android 平台实现 | |utssdk/app-harmony/index.uts| HarmonyOS | UTS |SelectorQuery/NodesRef的鸿蒙平台实现 |二、公共类型契约interface.uts 定义了什么所有平台实现共同引用 interface.uts该文件定义了插件对外暴露的完整类型体系。2.1 NodeInfo节点信息结果NodeInfo是查询回调中返回的节点信息对象字段如下| 字段 | 类型 | 含义 | | -- | -- | -- | |id|string \| null| 节点的 ID | |dataset|UniDOMStringMap \| null| 节点的 dataset | |left/right/top/bottom|number \| null| 节点四条边界坐标相对显示区域单位 px | |width/height|number \| null| 节点尺寸 | |scrollLeft/scrollTop|number \| null| 节点的水平 / 垂直滚动位置 | |scrollHeight/scrollWidth|number \| null| 节点内容高度 / 宽度 | |node|any \| null| 元素UniElement实例 | |context|any \| null| 节点对应的 Context 对象uni-app x 暂仅支持获取 EditorContext |2.2 NodeField按需查询的字段开关NodeField用于在fields()调用中声明“需要返回哪些信息”全部为可选的 boolean 或字段列表id是否返回节点 iddataset是否返回节点 datasetrect是否返回节点布局位置left right top bottomsize是否返回节点尺寸width heightscrollOffset是否返回scrollLeft/scrollTop节点必须是 scroll-view 或 viewportproperties属性名列表返回节点对应属性的当前值只能获取组件文档标注的常规属性id、class、style 及事件绑定属性不可获取computedStyle样式名列表返回节点对应样式的当前计算值context是否返回节点对应的 Context 对象node是否返回节点对应的 Node 实例。2.3 NodesRef 与 SelectorQuery链式调用接口NodesRef一次选择得到的引用提供四个查询动作每个动作都会向查询队列压入一条请求并返回SelectorQuery以便继续链式调用boundingClientRect(callback?)添加节点布局位置查询相对显示区域、以像素为单位scrollOffset(callback)添加节点滚动位置查询同样以像素为单位fields(fields, callback?)按NodeField指定字段获取节点相关信息context(callback)添加 Context 对象查询请求node(callback)获取 Node 节点实例目前支持 Canvas 的获取。SelectorQuery一次查询的起始对象提供以下方法in(component)将选择器选取范围更改为自定义组件内select(selector)在当前页面选择第一个匹配选择器的节点selectAll(selector)选择所有匹配选择器的节点selectViewport()选择显示区域viewportexec(callback?)执行所有已排队的请求回调参数为Arrayany结果数组。Uni接口声明了扩展挂载点createSelectorQuery(): SelectorQuery即插件最终注入到全局uni对象上的方法。三、Android 平台实现utssdk/app-android/index.uts 源码解读Android 实现位于 utssdk/app-android/index.uts是理解整条查询链路的最佳入口。它从dcloudio/uni-runtime引入getCurrentPage、isFunction等运行时能力并实现了三个核心类。3.1 请求队列模型SelectorQueryImplSelectorQueryImpl内部维护两条平行队列_queue: ArraySelectorQueryRequest查询请求队列每条请求记录component作用组件、selector选择器、single是否只取第一个与fields需要哪些字段_queueCb: ArraySelectorQueryNodeInfoCallback | null与请求一一对应的回调队列。select、selectAll、selectViewport只是创建对应的NodesRefImpl分别以singletrue/false标记单节点与多节点查询viewport 则传入空选择器真正的“入队”动作发生在NodesRefImpl的boundingClientRect/scrollOffset/fields/context/node方法里它们通过_push()把请求和回调分别追加到两条队列尾部这正是exec()能按序分发结果的基础。3.2 执行时机等待原生渲染完成exec()是查询真正发生的时刻Android 实现的特殊之处在于this._component?.$?.$waitNativeRender(() { ... })$waitNativeRender保证查询发生在原生视图渲染完成之后避免在布局尚未完成时拿到过时或全零的坐标。随后调用requestComponentInfo()遍历请求队列将res.forEach出的每一条结果按索引匹配到对应回调并执行若exec传入整体回调还会在末尾追加调用一次。3.3 节点定位QuerySelectorHelperQuerySelectorHelper承担了“找到节点并提取信息”的脏活累活其实现细节很值得注意注释节点fragment处理query()首先判断element.nodeName #comment。对多根节点组件uni-app x 会以注释节点作为虚拟容器此时走queryFragment()利用getNodeId()计算起始节点号从nextSibling开始向后遍历兄弟节点直到越过结束标记endNodeId从而把“多根节点”当作一个片段整体查询——这解释了示例页面中“子组件多根节点”能被正确选中的原因自身匹配querySelf()解析选择器首字符.走classList.includes#走getAttribute(id)否则按nodeName大小写不敏感比较用于支持“选择器命中容器自身”的场景信息提取getNodeInfo()按fields决定返回内容。若node: true则直接返回UniElement实例附带可选的 dataset 与 size否则通过getBoundingClientRect()组装id、left/top/right/bottom、width/height并按需附加 dataset。最终createSelectorQuery工厂方法以当前页面getCurrentPage()为默认作用域创建SelectorQueryImpl实例。四、鸿蒙平台实现utssdk/app-harmony/index.uts 源码解读鸿蒙实现位于 utssdk/app-harmony/index.uts整体结构与 Android 版对称但有三处明显差异API 注册方式不同鸿蒙版使用defineSyncApiSelectorQuery(createSelectorQuery, ...)注册同步 API并重新导出interface.uts中的全部类型入口函数会优先使用传入的context通过resolveComponentInstance解析并用getPageIdByVm(context)校验其确实属于某个页面否则回退到getCurrentPageVm()作用域解析in()方法通过resolveComponentInstance(component)将组件实例统一解析为ComponentPublicInstance原生渲染等待下沉鸿蒙版不再显式调用$waitNativeRender而是直接调用运行时导入的requestComponentInfo说明原生查询等待逻辑由dcloudio/uni-runtime在鸿蒙侧统一封装。两份平台实现都保留了注释掉的ContextClassscanvas/map/video/editor Context 工厂与convertContext逻辑结合interface.uts中context字段“uni-app x 暂仅支持获取 EditorContext”的注释可以推断 Context 化查询能力仍在逐步完善中。五、典型用法从示例页面到真实场景仓库示例页 create-selector-query.uvue 完整演示了本插件的各类查询姿势可直接对照学习。5.1 单节点布局信息select boundingClientRectuni.createSelectorQuery().select(.rect1).boundingClientRect().exec((ret) { const i ret[0] as NodeInfo data.nodeInfoList.push({ left: i.left, top: i.top, right: i.right, bottom: i.bottom, width: i.width, height: i.height, }) })5.2 多节点布局信息selectAlluni.createSelectorQuery().selectAll(.rect).boundingClientRect().exec((ret) { const array ret[0] as NodeInfo[] // 第一个结果即 NodeInfo 数组 array.forEach((i) { /* 处理每个节点 */ }) })5.3 按字段查询fields / node示例在onReady阶段分别验证了fields({ node: true })与node()获取节点实例的能力uni.createSelectorQuery().select(.rect1).fields({ node: true } as NodeField, (ret) { const isElement (ret as NodeInfo).node instanceof UniElement ... }).exec() uni.createSelectorQuery().select(#canvas1).node((ret) { const isCanvasElement ((ret as NodeInfo).node as UniCanvasElement).tagName CANVAS ... }).exec()可见fields与node返回的都是UniElement/UniCanvasElement等原生元素实例可用于进一步的 DOM 操作。5.4 限定组件范围in在自定义组件内部查询时需先取得组件实例再限定范围。子组件示例 nodes-info-child.uvue 展示了标准写法const instance getCurrentInstance()!.proxy! onMounted(() { uni.createSelectorQuery().in(instance).select(.selector-query-child-view) .boundingClientRect().exec((ret) { if (ret.length 1) { const nodeInfo ret[0] as NodeInfo data.top nodeInfo.top! } }) })配合onScroll场景的 create-selector-query-onScroll.uvue滚动时对content-item批量selectAll查询与 selector-query-child-multi.uvue子组件多根节点查询、用于验证查询不越出作用域可覆盖绝大多数实际需求。5.5 自动化测试佐证对应自动化用例 create-selector-query-onScroll.test.js 展示了该 API 的端到端验证方式通过program.reLaunch打开页面、program.swipe模拟滚动再断言页面数据data.ret保持为true即exec回调在滚动事件中同步被触发。注意该用例对 Web、小程序、DOM2 模式与横屏设备直接跳过验证了本插件在部分平台的实现差异。六、平台与版本兼容性interface.uts中的uniPlatform注释给出了各平台能力矩阵以 unixVer 即 uni-app x 版本号标注要点如下createSelectorQuery 基础能力Android 需 uni-app x 3.91Vapor 5.21、iOS 4.11、鸿蒙 4.61Vapor 5.0各小程序与 Web 端在 uni-app x 4.0/4.41 起可用fields 多字段查询Android/iOS 自 4.25 起支持微信小程序 4.41Web 4.0context 查询EditorContext 等Android/iOS 5.04、鸿蒙 5.04 起支持小程序端目前仅微信4.41支持支付宝、百度、抖音、飞书、QQ、快手、京东标注为x不支持Node 实例获取与fields同版本线Android/iOS 4.25支持并注明目前支持 Canvas 的获取。从源码注释看node字段在app-android侧未单独标记uniPlatform鸿蒙侧context则覆盖到 5.04不同字段的可用版本需以目标 HBuilderX 与 uni-app x 版本实际行为为准。七、插件背后的 UTS 语言阅读本插件源码尤其是interface.uts前有必要理解其载体语言。utsuni type script是一门跨平台、高性能、强类型的现代编程语言可编译为不同平台的编程语言| 平台 | 编译目标语言 | | -- | -- | | Android | Kotlin | | iOS | Swift | | HarmonyOS鸿蒙 | ArkTS | | Web / 小程序 | JavaScript |uts 采用了与 TypeScript 基本一致的语法规范支持绝大部分 ES6 API但为了跨端一致性uts 进行了一些约束与平台特定增补。过去在 JS 引擎下运行的语法大部分在 uts 下可平滑用于 Kotlin 与 Swift但仍有一些差异无法抹平需要使用条件编译——与 uni-app 的条件编译类似写在条件编译块里的代码可以调用平台特有的扩展语法。本插件正是这一能力的最佳体现同一份interface.uts类型契约被编译成 KotlinAndroid与 ArkTS鸿蒙两套实现。八、UTS 插件与扩展 API 的组织方式UTS 插件是一种特定的 uni_modules 插件核心目的是允许 uni-app / uni-app x 开发者使用 UTS 语法调用扩展 API封装原生系统 API 或三方 SDK。其实现代码主要位于utssdk目录并按平台分离组织| 目录/文件 | 目标平台 | 实现语言 | 作用描述 | | -- | -- | -- | -- | |utssdk/app-android| Android | UTS, Kotlin, Java | 存放 UTS 插件在 Android 平台上的具体实现源码 | |utssdk/app-ios| iOS | UTS, Swift | 存放 UTS 插件在 iOS 平台上的具体实现源码 | |utssdk/app-harmony| HarmonyOS鸿蒙 | UTS, ArkTS | 存放 UTS 插件在 HarmonyOS 平台上的具体实现源码 | |utssdk/*.uts| 多平台共用 | UTS | 存放使用 UTS 编写的、可供所有平台共用的实现源码 |uni-createSelectorQuery 严格遵循这一规范公共类型放utssdk/interface.utsAndroid 与鸿蒙实现各自独立成包package.json通过uni-ext-api声明挂载到uni全局对象从而让uni.createSelectorQuery()在不同端拥有统一调用体验。仓库内 docs/plugin/uts-plugin.md、docs/plugin/uts-for-android.md、docs/plugin/uts-for-ios.md、docs/plugin/uts-for-harmony.md 提供了 UTS 插件与原生混编开发的完整说明可作为进一步深入的材料。九、小结uni-createSelectorQuery 是一个结构规整、跨端实现清晰的 UTS 插件范本interface.uts定义统一的类型契约Android 版用$waitNativeRender保证布局就绪并自行实现选择器解析含多根节点片段查询鸿蒙版借助defineSyncApi与运行时requestComponentInfo完成接入最终通过uni_modules元数据挂载为uni.createSelectorQuery全局 API。无论是直接使用select/selectAll/fields/node获取节点信息还是参考其目录组织方式开发自己的 UTS 扩展 API本插件都是值得精读的参考实现。赞分享示例工程前端移动开发跨平台【免费下载链接】uni-appA cross-platform framework using Vue.js项目地址https://gitcode.com/gh_mirrors/un/uni-app点击查看免费下载相关推荐uni-app/uni-app x 组件相交监听实战uni-createIntersectionObserver UTS 插件源码解析与使用指南uni app/uni app x 组件相交监听实战uni createIntersectionObserver UTS 插件源码解析与使用指南 本篇技术指南示例工程前端移动开发跨平台uni-app x uni-exit 插件跨端退出应用 API 的源码解析与实战指南uni app x uni exit 插件跨端退出应用 API 的源码解析与实战指南 uni exit 是 uni app/uni app x 生态中一个轻量示例工程前端移动开发跨平台uni-interceptor 拦截器插件源码解析uni-app x 路由与扩展 API 拦截实战指南uni interceptor 拦截器插件源码解析uni app x 路由与扩展 API 拦截实战指南 uni app x 中的 uni intercepto示例工程前端移动开发跨平台上一篇Diffy架构详解代理层、比较器与提升器的完美协作下一篇【亲测免费】 深入探索用户意图识别利用 Intent-Model 模型优化问答系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考