Taro开发——MovableView兼容性处理与排查

204 阅读1分钟

需求描述:

icon固定在页面左右4px范围,全页面范围内拖动,为避免与小程序顶部胶囊重合,回弹距离顶部200px

问题描述:

  • 微信小程序场景:拖动到顶部时,改变x,y值无法回归左右两侧
  • alipayHK小程序场景:具有滚动穿透的遗留问题概述 | Taro 文档
  • h5场景:会将拖动内容当成自己的父容器,且x,y值监听处理机制有问题

问题排查过程:

  1. alipayHK小程序的滚动穿透,通过尝试taro给出的两种方案,只有通过修改页面布局解决
  2. 改变x,y值无法回归左右两侧问题,查询taro库issues,有RN类似issue,但官网暂未修复github.com
  3. 通过查阅taro源码,查看watchX方法,只有在x值发生变化时,才会更改icon坐标。代码处理方式有问题x值拖动时在同一侧时,不会发生变化,于是拖动icon无法回弹,无监听开始拖动与结束拖动的API,如果贸然修改X值,会触发change事件,导致死循环。

@Watch('x')
 watchX (newValue: number | string) {
   this.setTransform(parseFloat(`${newValue || 0}`), this.translateY)
 }

4. 再查看setTransform源码,发现只有translateX或translateY数字值变化时,会触发change事件,但是WatchX值,可以为number|string,根据vue3 watch的特性,不是全等值会触发watch事件,如果为同一侧,那就字符串数字与数字切换,不会产生死循环,又能改变坐标

watchX (newValue: number | string)

private translateX: number = 0

setTransform = (x: number, y: number, scale?: number, source?: string, noEmitChange?: boolean, emitScale?: boolean) => {
    x = Number(x.toFixed(1))
    y = Number(y.toFixed(1))
    if (this.translateX !== x || this.translateY !== y) {
      !noEmitChange && this.onChange.emit({
        x: realX,
        y: realY,
        source
      })
    }

  //...
   const transform = `translateX(${x}px) translateY(${y}px) translateZ(0px) scale(${scale})`
    this.element.style.transform = transform
    this.element.style.webkitTransform = transform
    this.translateX = x
    this.translateY = y
    this.currentScale = scale
  //...
  }

5. h5将自己当成父容器,查看taro源码,是父容器获取MovableView的时机无法满足需求,在h5中componentDidLoad时机跟平常vue3项目不同,但无法修改taro源码改变运行机制,于是将v-if修改为v-show

 /** 子元素集合 */
  private views: Array<HTMLElement> = []
  
  componentDidLoad () {
    this.viewsChanged()
  }

  viewsChanged = () => {
    this.views = []
    const elements = this.element.querySelectorAll('taro-movable-view-core')
    Array.from(elements).forEach((element) => {
      this.views.push(element)
    })
    this.updateArea()
  }

反思改进:

排查问题强类型语言更简洁直观。