uni-app 自定义组件中使用uni.createSelectorQuery()获取节点信息在屏幕翻转后信息不正确
uni-app 自定义组件中使用uni.createSelectorQuery()获取节点信息在屏幕翻转后信息不正确
项目信息 | 详情 |
---|---|
产品分类 | uniapp/App |
PC开发环境操作系统 | Windows |
PC开发环境操作系统版本号 | Win10 |
HBuilderX类型 | 正式 |
HBuilderX版本号 | 4.28 |
手机系统 | Android |
手机系统版本号 | Android 10 |
手机厂商 | 小米 |
手机机型 | Redmi |
页面类型 | vue |
vue版本 | vue3 |
打包方式 | 云端 |
项目创建方式 | HBuilderX |
示例代码:
const GetRect = (selector : string, context ?: any, all = false) => {
return new Promise((resolve, reject) => {
try {
let query = uni.createSelectorQuery();
if (context) {
query = uni.createSelectorQuery().in(context);
}
query[all ? "selectAll" : "select"]
.boundingClientRect(function (rect) {
if (all && rect && Array.isArray(rect) && rect.length) {
resolve(rect);
}
if (!all && rect) {
resolve(rect);
}
resolve(rect);
})
.exec();
} catch (e) {
//TODO handle the exception
}
});
}
const calcScrollXWidth = async () => {
const rect = await GetRect(`#cont-box-${formId.value}`, proxy, true);
console.log('cont-box', rect)
if (rect) {
let maxRect = 0
if (Array.isArray(rect)) {
rect.forEach((item) => {
if (!maxRect) {
maxRect = item.width
} else if (maxRect < item.width) {
maxRect = item.width
}
})
}
if (maxRect) {
scorllXWidth.value = maxRect
}
}
}
操作步骤:
将屏幕从横屏翻转为竖屏后使用 uni.createSelectorQuery()获取节点的宽高
预期结果:
获取当前屏幕状态下的节点宽高
实际结果:
取到的是横屏下的宽高
bug描述:
在使用uni.createSelectorQuery()获取自定义组件的节点宽度和高度时,屏幕先由竖屏翻转为横屏此时获取的宽高是正确的,从横屏翻转为竖屏此时再获取宽高就一直是横屏时的宽高
2 回复
折叠屏竖屏 请求 createQuerySelector 查询正常,切换为横屏之后查询正常,再切换为竖屏不正常是吗?如果不是请具体描述一下场景。
如果等两秒再请求是否正常?请排查下是功能有延迟,还是功能调整几次之后功能坏了
在 uni-app 中,如果你在自定义组件中使用 uni.createSelectorQuery()
获取节点信息,并且在屏幕翻转后发现获取的信息不正确,这通常是因为页面布局在屏幕翻转后发生了变化,但查询操作可能还在旧的布局状态下执行。为了解决这个问题,你需要在屏幕翻转事件后重新执行节点查询。
以下是一个示例代码,展示如何在自定义组件中处理屏幕翻转事件并重新获取节点信息:
<template>
<view class="container">
<view ref="targetNode" class="target-node">Target Node</view>
</view>
</template>
<script>
export default {
data() {
return {
nodeInfo: null,
};
},
methods: {
queryNodeInfo() {
const query = uni.createSelectorQuery().in(this);
query.select('#targetNode').boundingClientRect(data => {
this.nodeInfo = data;
console.log('Node Info:', data);
}).exec();
},
handleOrientationChange() {
// 清空旧信息,准备获取新信息
this.nodeInfo = null;
this.queryNodeInfo();
},
},
mounted() {
// 初始查询
this.queryNodeInfo();
// 监听屏幕翻转事件
const page = getCurrentPages()[getCurrentPages().length - 1];
if (page) {
const orientationChangeHandler = this.handleOrientationChange;
page.onOrientationChange = orientationChangeHandler; // 假设uni-app支持直接给页面对象添加事件监听(注意:实际使用可能需要调整)
// 如果需要,也可以监听系统级的resize事件(注意性能影响)
// window.addEventListener('resize', orientationChangeHandler);
// 在组件卸载时移除监听器
this.$once('hook:beforeDestroy', () => {
if (page.onOrientationChange === orientationChangeHandler) {
delete page.onOrientationChange;
}
// 如果添加了window的resize监听器,也需要移除
// window.removeEventListener('resize', orientationChangeHandler);
});
}
},
};
</script>
<style>
.container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
.target-node {
width: 100px;
height: 100px;
background-color: red;
}
</style>
注意:
getCurrentPages()
和直接给page
对象添加事件监听器的方式可能需要根据实际 uni-app 的版本和特性进行调整。如果onOrientationChange
不是页面对象的有效属性,你可能需要寻找其他方式来监听屏幕翻转事件,例如使用uni.onWindowResize
(如果存在)。- 组件中直接操作页面对象可能不是最佳实践,但在某些情况下可能是必要的。通常,更好的做法是使用全局状态管理或事件总线来处理这类跨组件/页面的通信。