vant使用postcss-px-to-viewport转化单位产生的pullRefresh 刷新中高度问题

430 阅读2分钟

vant的pullRefresh 刷新中高度问题

在手机小屏下拉刷新,内容的高度没问题

image-20220901112359444

但在ipad这种大屏的显示就出现问题了,有部分被遮住了

image-20220901112532178

因为我的项目使用了postcss-px-to-viewport转化单位,其实内容高度也进行了单位转换,也没有毛病

image-20220901112756249

既然高度没问题,那肯定是定位之类的位置不对,导致一部分被遮住,然后我看到了上面的绝对定位,但是又没有top值😓

然后我把loading的状态设置为true来调试,发现是van-pull-refresh__track这个节点的内联样式translate3d(0,50px, 0)控制位置的。

那么问题就知道了,这个内联样式是vant组件内部算的,而且是px,因为postcss-px-to-viewport不能转换行内样式的单位

那就看看源码(点击查看)是怎么处理的吧

const trackStyle = {
  transitionDuration: `${state.duration}ms`,
  transform: state.distance
  ? `translate3d(0,${state.distance}px, 0)`
  : '',
};

确实是根据设置的距离的值做的,接下来就看他touchEnd做了什么就可以了

因为这个问题就是手松开之后,组件的translateY位置不对

const onTouchEnd = () => {
  if (reachTop && touch.deltaY.value && isTouchable()) {
    state.duration = +props.animationDuration;

    if (state.status === 'loosing') {
      // 松手后就是刷新中,就是在这个地方设置了展示内容的一个高度
      setStatus(+props.headHeight, true);
      emit('update:modelValue', true);

      // ensure value change can be watched
      nextTick(() => emit('refresh'));
    } else {
      setStatus(0);
    }
  }
};
// ...
const setStatus = (distance: number, isLoading?: boolean) => {
  const pullDistance = +(props.pullDistance || props.headHeight);
  state.distance = distance;

  if (isLoading) {
    state.status = 'loading';
  } else if (distance === 0) {
    state.status = 'normal';
  } else if (distance < pullDistance) {
    state.status = 'pulling';
  } else {
    state.status = 'loosing';
  }

  emit('change', {
    status: state.status,
    distance,
  });
};

由此可见,在touchEnd的时候通过setStatus方法把props.headHeight(默认50)的值作为Y轴偏移的距离

解决办法

所以,根据当前设备的宽高(根据UI设计稿或者你自己的适配方案)去计算高度,设置headHeight的值,单位是px

其实我记录的时候UI还没设计,但是375下我感觉vant默认的50px挺合适的,所以就定义了750的时候设置headHeight100

<template>
  <div>
    <PullRefresh :head-height="changeUiPx(100)" success-text="刷新成功" v-bind="$attrs">
      <slot></slot>
    </PullRefresh>
  </div>
</template>
<script lang="ts" setup>
  import { PullRefresh } from 'vant';
  import { changeUiPx } from '/@/utils';
</script>
<style lang="less" scoped></style>

我自己写了一个转换我们设计稿(宽750)单位的工具函数

import { useWindowSize } from '@vant/use';
/**
 * @author: gauharchan
 * @description 设计稿像素转换
 * @param {number} value 设计稿实际的值
 */
export const changeUiPx = (value: number) => {
  const { width, height } = useWindowSize();
  const vmin = Math.min(width.value, height.value);
  return (vmin * value) / 750;
};