【taro react】---- 获取元素的位置和宽高等信息

1. 需求分析

  1. 添加节点的布局位置的查询请求。相对于显示区域,以像素为单位。其功能类似于 DOM 的 getBoundingClientRect。返回 NodesRef 对应的 SelectorQuery。
  2. 区分小程序和H5的环境,调用 getBoundingClientRect 获取对应的信息。

2. H5 实现

  1. 判断传入元素是否是window窗口,是window窗口,直接获取窗口的宽高;
  2. 元素,同时可以获取元素的宽高等信息;
  3. 都不满足,返回默认值。
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 实现

  1. 元素存在,判断使用对应环境获取元素信息;
  2. H5环境使用元素的获取元素信息方法;
  3. 微信小程序环境调用 boundingClientRect 获取元素信息;
  4. 返回默认值。
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,
  })
}

猜你喜欢

转载自blog.csdn.net/m0_38082783/article/details/132034815