开发小结(08.11-08.16)

本周一直在做 uniapp 的微信小程序项目,因此涉及的问题都是在该场景下出现

scroll-view 高度计算

在涉及下拉刷新和上拉加载的场景,scroll-view 是不错的选择,使用的时候需要传一个固定高度,如何准确计算出滚动区域高度,就很重要

如图,底部粉色区域为滚动区域,要计算滚动区域高度,用页面高度(100vh)减去其他区域(红色,绿色,蓝色)高度即可,还需要注意在滚动区域以外,如果有设置 marginTop,marginBottom,也要减去这个高度

在设计页面的时候,最好区分好每个部分的功能,不仅开发起来方便,也有利于计算高度,最后得出滚动区域高度

javascript 复制代码
this.scrollViewHeight = `calc(100vh - (${statusBarHeight}px + ${navigationBarHeight}px + ${uni.upx2px(290)}px + ${uni.upx2px(44 + 10)}px))`;

红框部分实现的是自定义导航栏:高度为${statusBarHeight}px + ${navigationBarHeight}px

蓝框部分用rpx设置的相对高度,需要用uni.upx2px(290)

蓝框部分设置的44rpx加上蓝框和红框之间margin,同样要用uni.upx2px(44 + 10)转化

这样就能准确得出滚动区域高度,但如果其他区域没有设置高度,如何获取该区域高度呢,请接着看自定义 tabbar

自定义 tabbar

还是上面的页面,我需要实现一个 tabbar,要求当前激活项下显示红色短线,并且切换项目时候,短线有移动动画

先根据需求设置基本样式,.tab-item为选项卡部分,.active-bar为底部红色短线

vue 复制代码
  <view class="tabs">
    <view v-for="(item, idx) in tabList" :key="item.name" class="tab-item"
      :class="{ active: idx === activeTabIndex }" @click="changeTab(idx)">
      {{ item.name }}
    </view>
    <view class="active-bar" :style="{
          left: activeBarLeftPx + 'px'
        }">
    </view>
  </view>

部分样式

css 复制代码
.active-bar {
  position: absolute;
  bottom: -6rpx;
  height: 6rpx;
  border-radius: 30rpx;
  background-color: rgba(255, 43, 88, 1);
  width: 40rpx;
}

难点在于获取当前选项卡的位置,才能正确设置短线的位置,因为在 uni 的小程序平台不支持页面的 ref 属性,这里要用到uni.createSelectorQueryapi

在页面加载完成后,查询默认第一个选项卡位置

vue 复制代码
mounted() {
  // 初始化时获取第一个tab的位置
  this.$nextTick(() => {
    this.queryTabRect(this.activeTabIndex);
  });
},
  
methods: {
  queryTabRect(idx) {
    uni.createSelectorQuery()
      .in(this)
      .selectAll('.tab-item')
      .boundingClientRect(rects => {
        if (rects && rects[idx]) {
          this.activeBarLeftPx = rects[idx].left + (rects[idx].width - uni.upx2px(40)) / 2; // 相对导航栏左侧
        }
      })
      .exec();
  },
}

this.activeBarLeftPx.active-bar相对父容器的距离,如何计算距离呢,rects[idx].left是当前选项卡距离父容器左边距,(rects[idx].width - uni.upx2px(40)) / 2是选项卡和底部短线在竖直方向居中对齐时,多出来长度的一半,加上这个长度,就能正确计算出底部短线距离父容器左边框的距离

容器高度

回到上面scroll-view 高度计算部分,其他区域高度也可以使用uni.createSelectorQueryapi 获取,结果就是rects[idx].height,需要注意这个高度不包括padding,所以计算高度时候需要加上padding

单行文字省略效果

小程序里有一个排行榜的页面,每条记录可能存在名称或者数值溢出的情况,可以考虑使用 css 实现文字溢出显示省略号的功能,不过需要注意使用条件

text-overflow 用于确定如何提示用户存在隐藏的溢出内容,但需要为容器设置准确宽度

从上图分析,内容区域宽度为蓝色区域的宽度,左边文字部分和右边数字部分可能存在溢出情况,就需要给这两个部分添加溢出样式

css 复制代码
  .overflow-style {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

还需要设置准确的宽度,溢出效果才能生效,右边可以设置固定宽度100rpx,左边宽度如何计算呢,左边文字区域宽度可以用总宽度100%- 奖牌宽度 - 头像宽度,结果就是文字宽度

由于左边部分存在层级嵌套关系,我们可以逐层计算得出文字宽度

.left计算出左边宽度width: calc(100% - 110rpx),多 10rpx 为了在左右区域之间加个间隔

.info计算出除奖牌宽度,剩余宽度width: calc(100% - 60rpx)

.name计算出除头像宽度,剩余文字宽度width: calc(100% - 70rpx)

示例部分省略代码如下

vue 复制代码
...
  <view v-for="(item, index) in otherRankList" class="item">
    <view class="left">
      <template v-if="index < 3">
        <image :src="getMedal(index)" mode="aspectFit" class="medal" />
      </template>
      <template v-else>
        <view class="rank">{{ index + 1 }}</view>
      </template>
      <view class="info">
        <image class="avatar" :src="item.avatar" mode="scaleToFill" />
        <view class="name">{{ item.name }}</view>
      </view>
    </view>
    <view class="right">{{ item.value }}</view>
  </view>
...
      .other-rank {
        border-radius: 40rpx 40rpx 0 0;
        width: 100%;
        height: 100%;
        padding: 10rpx 54rpx;
        box-sizing: border-box;
        position: relative;
        z-index: 2;

        .item {
          @include flex-center;
          position: relative;
          justify-content: space-between !important;
          gap: 10rpx;
          height: 110rpx;
          width: 100%;

          .left {
            @include flex-center;
            justify-content: flex-start !important;
            gap: 20rpx;
            width: calc(100% - 110rpx);

            .medal {
              width: 40rpx;
              height: 50rpx;
            }

            .rank {
              width: 40rpx;
              text-align: center;
              font-size: 32rpx;
              font-weight: 700;
              color: #B4B6C0;
            }

            .info {
              @include flex-center;
              justify-content: flex-start !important;
              flex: 1;
              gap: 20rpx;
              width: calc(100% - 40rpx);

              .avatar {
                width: 50rpx;
                height: 50rpx;
                border-radius: 50%;
              }

              .name {
                width: calc(100% - 50rpx);
                white-space: nowrap;
                overflow: hidden;
                text-overflow: ellipsis;
              }
            }
          }

          .right {
            width: 100rpx;
            text-align: right;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
          }

        }
      }

注意

计算宽度也要把gap考虑在内,如果忽略了gap,在文字溢出时候,图片宽度会被压缩,这时候有两种方法解决

  1. 正确计算对应区域宽度,如果有gap,减去gap宽度
  2. 在被压缩的容器上添加样式flex-shrink: 0,在宽度不足时,禁止压缩

小程序动态样式

页面内如果绑定动态样式,类如

vue 复制代码
<template>
  <view :style="customStyle"></view>
</template>

<script>
  export default {
    data() {
      return {
        customStyle: {
          fontSize: '16px'
        }
      }
    }
  }
</script>

这种写法编译在微信平台并不能生效,正确写法是:style="[customStyle]"

相关推荐
Juchecar1 分钟前
Vue3 事件处理 v-on 指令 (@) 详解
前端·vue.js
晴空雨2 分钟前
💯 React 渲染优化策略:避免不必要的重渲染
前端·react.js
奶昔不会射手13 分钟前
css3之flex布局
前端·css3·flex
跟橙姐学代码18 分钟前
Python 装饰器超详细讲解:从“看不懂”到“会使用”,一篇吃透
前端·python·ipython
pany37 分钟前
体验一款编程友好的显示器
前端·后端·程序员
Zuckjet42 分钟前
从零到百万:Notion如何用CRDT征服离线协作的终极挑战?
前端
ikonan1 小时前
译:Chrome DevTools 实用技巧和窍门清单
前端·javascript
Juchecar1 小时前
Vue3 v-if、v-show、v-for 详解及示例
前端·vue.js
ccc10181 小时前
通过学长的分享,我学到了
前端
编辑胜编程1 小时前
记录MCP开发表单
前端