1. 需求分析
- 添加节点的布局位置的查询请求。相对于显示区域,以像素为单位。其功能类似于 DOM 的 getBoundingClientRect。返回 NodesRef 对应的 SelectorQuery。
- 区分小程序和H5的环境,调用 getBoundingClientRect 获取对应的信息。
2. H5 实现
- 判断传入元素是否是window窗口,是window窗口,直接获取窗口的宽高;
- 元素,同时可以获取元素的宽高等信息;
- 都不满足,返回默认值。
function isWindow(val){
return val === window
}
export const getRect = (elementRef) => {
const element = elementRef
// 判断传入元素是否是window窗口,是window窗口,直接获取窗口的宽高
if (isWindow(element)) {
const width = element.innerWidth
const height = element.innerHeight
return {
top: 0,
left: 0,
right: width,
bottom: height,
width,
height,
}
}
// 是元素,同时可以获取元素的宽高等信息
if (element && element.getBoundingClientRect) {
return element.getBoundingClientRect()
}
// 都不满足,返回默认值
return {
top: 0,
left: 0,
right: 0,
bottom: 0,
width: 0,
height: 0,
}
}
3. Taro 实现
- 元素存在,判断使用对应环境获取元素信息;
- H5环境使用元素的获取元素信息方法;
- 微信小程序环境调用 boundingClientRect 获取元素信息;
- 返回默认值。
export const getRectByTaro = async (element) => {
// 元素存在,判断使用对应环境获取元素信息
if (element) {
if(process.env.TARO_ENV === "h5"){
// H5环境使用元素的获取元素信息方法
return Promise.resolve(getRect(element))
} else if(process.env.TARO_ENV === "weapp"){
// 微信小程序环境调用 boundingClientRect 获取元素信息
return new Promise((resolve) => {
createSelectorQuery()
.select(`.${element.props.class.split(' ').filter(item => item).join('.')}`)
.boundingClientRect(resolve).exec()
})
}
}
// 返回默认值
return Promise.resolve({
top: 0,
left: 0,
right: 0,
bottom: 0,
width: 0,
height: 0,
})
}
4. 使用实例
1. 引入
import React, { Component } from 'react';
import { getRectByTaro } from '@utils/use-client-rect';
2. 获取 dom 的 getBoundingClientRect 信息
class page extends Component {
constructor(props) {
this.navbarRef = React.createRef()
}
componentDidShow(){
// 如果元素内有动态信息,需要将获取信息的方法放到请求数据完成,设置数据后边
this.getElementInfo()
}
getElementInfo(){
let _this = this;
let timer = setTimeout(async () => {
clearTimeout(timer)
console.log('_this.navbarRef',_this.navbarRef.current)
let info = await getRectByTaro(_this.navbarRef.current)
console.log('navbarRef', info)
},0)
}
render() {
return (<View className='rui-navbar-current-content' ref={this.navbarRef}></View>)
}
}
5. 微信小程序返回样例
6. H5 返回样例
7. 完整代码
import { createSelectorQuery } from '@tarojs/taro';
function isWindow(val){
return val === window
}
export const getRect = (elementRef) => {
const element = elementRef
// 判断传入元素是否是window窗口,是window窗口,直接获取窗口的宽高
if (isWindow(element)) {
const width = element.innerWidth
const height = element.innerHeight
return {
top: 0,
left: 0,
right: width,
bottom: height,
width,
height,
}
}
// 是元素,同时可以获取元素的宽高等信息
if (element && element.getBoundingClientRect) {
return element.getBoundingClientRect()
}
// 都不满足,返回默认值
return {
top: 0,
left: 0,
right: 0,
bottom: 0,
width: 0,
height: 0,
}
}
export const getRectByTaro = async (element) => {
// 元素存在,判断使用对应环境获取元素信息
if (element) {
if(process.env.TARO_ENV === "h5"){
// H5环境使用元素的获取元素信息方法
return Promise.resolve(getRect(element))
} else if(process.env.TARO_ENV === "weapp"){
// 微信小程序环境调用 boundingClientRect 获取元素信息
return new Promise((resolve) => {
createSelectorQuery()
.select(`.${element.props.class.split(' ').filter(item => item).join('.')}`)
.boundingClientRect(resolve).exec()
})
}
}
// 返回默认值
return Promise.resolve({
top: 0,
left: 0,
right: 0,
bottom: 0,
width: 0,
height: 0,
})
}