vue3在h5及小程序中滚动吸顶及(动态超出文本折叠)

 前言

在vue3中滚动至一定高度tab按钮吸顶(h5中在header下、小程序中置顶),动态计算出后台返回的数据长度通过长度展示不同的样式

目录

一、templete部分

 二、script部分

三、style

四、展示效果

五、白屏问题


一、templete部分

<template>
  <div @scroll="changeScroll" class="series_container">
    <v-header :headerOpt="headerOpt" :title="title"></v-header>
      <div id="bannerfix">
        <div class="banner">
        <img class="bannerImg" src="https://img-blog.csdnimg.cn/a432feb7b8c445dc8df68f71cabdc584.png?x-oss-process=image/resize,m_fixed,h_300,image/format,png" alt="">
      </div>
      <div class="desbox">
        <div class="title">我是标题1111111111111111111111111111111111111111111111111111111</div>
        <div class="des_flex">
          <div ref="descontent" :class="['des',desFlag?'showFlag':'']">我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述我是详情描述</div>
          <div v-if="!showdesFlag" :class="['btn',desFlag?'':'showbtn']" @click="desFlag=!desFlag"></div>
        </div>
      </div>
      </div>
      <div :class="['series_main',scrollTopflag?'mainfix':'']">
         <div :class="['tab',scrollTopflag&&isWechat?'tabfix1':'',scrollTopflag&&!isWechat?'tabfix':'']">
          <div :class="['tab_btn',chooseTab==1?'tabActive':'']" @click="changeTab(1)">tab1<div class="border"></div></div>
          <div :class="['tab_btn',chooseTab==2?'tabActive':'']" @click="changeTab(2)">tab2</div>
        </div>
        <div v-if="chooseTab==1">
          <div class="series_detail">测试数据</div>
        </div>
        <div class="ser_list" v-if="chooseTab==2">
          <div class="ser_item" @click="toDetail(item)" v-for="(item,index) in 10" :key="index+'index'">
            <div class="lef">
              <img class="lef_img" src="https://p.qqan.com/up/2022-9/16644325731126722.jpg" alt="">
            </div>
            <div class="rig">
              <div>
                <div class="rigtitle">我是目录标题</div>
              </div>
            </div>
          </div>
        </div>
      </div>
  </div>
</template>

 二、script部分

<script>
import { defineComponent, nextTick, onMounted, ref } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { seriesCourseDetail } from "../../api/class/class";
import header from '../../components/header.vue'
export default defineComponent({
  components: {
    "v-header":header,
  },
  setup() { 
    const router = useRouter(),
      route = useRoute()
    const title = ref(route.name || '')
    let seriesInfo=ref({})//详情信息
    let descontent=ref(null)//获取元素
    let desFlag=ref(false)//展示样式
    let chooseTab=ref(1)//选中tab
    let showdesFlag=ref(false)//是否展示按钮
    const u = navigator.userAgent;
    let isiOS=ref(false)
    let isWechat=ref(false)
    isWechat.value=sessionStorage.getItem("isminiPro") ? true : false;//是否小程序
    isiOS.value = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
    const headerOpt = ref({
      backUrl: "",
      backQuery: {},
    });
    const query = ref({
      queryStr: "",
      paramObj: {},
    });
    let scrollTopflag=ref(false)//滚动flag
    let redirectUri = "";
    let openId = ref("");
    //对参数处理
     const getParams = () => {
      let urlQuery = window.location.href.split("?")[1];
      let arr = urlQuery.split("&");
      let paramObj = {};
      arr.forEach((item) => {
        let itemArr = item.split("=");
        paramObj[itemArr[0]] = itemArr[1];
      });
      query.value.queryStr = urlQuery; // 结果示例:code=code&seriesCode=123
      query.value.paramObj = paramObj; // 结果示例:{ code: code, seriesCode:123 }
    };
    //修改选中tab
    const changeTab=(index)=>{
      chooseTab.value=index
    }
    //获取信息
    const getseriesCourseDetail=(params)=>{
      seriesCourseDetail(params).then((res)=>{
        if(res.data){
          seriesInfo.value=res.data
          nextTick(()=>{
            init()
          })
        }
      })
    }
    let init=()=>{  
      //计算课程介绍高度
      let lineHeight =22
      if(descontent.value.offsetHeight >lineHeight*1){
          desFlag.value=true      
      }else{
          showdesFlag.value=true
      }
    }  
    //fix顶部打开
    let changeScroll=(e)=>{
      let tarScro = e.target.scrollTop
      let fixheight=document.getElementById('bannerfix').clientHeight
      if(tarScro>=fixheight-10){
        // console.log('fix顶部了');
        scrollTopflag.value=true
      }else{
        scrollTopflag.value=false
      }
    }
    onMounted(() => {
      getParams()
    if(route.query.seriesCode){
      getseriesCourseDetail(route.query.seriesCode)
      }
    })
    return {
      title,
      chooseTab,
      seriesInfo,
      desFlag,
      descontent,
      showdesFlag,
      isiOS,
      isWechat,
      headerOpt,
      scrollTopflag,
      changeTab,
      changeScroll,
    }
  },
})
</script>

三、style

.series_container{
  height: 100vh;
  background-color: #F6F8FA;
  padding-bottom: 1.2rem;
  box-sizing: border-box;
  overflow-x: hidden;
  overflow-y: auto;
}
.series_container1{
  padding-bottom: 0;
}
.series_container .banner{
  height: 5.64rem;
  display: -webkit-box;
  -webkit-box-pack: center;
  -webkit-box-align: center;
  overflow: hidden;
}
.series_container .banner .bannerImg{
  max-width: 100%;
  max-height: 100%;
}
.series_container .desbox{
  padding: .32rem .24rem;
  background-color: #fff;
  margin-bottom: .2rem;
}
.series_container .desbox .title{
  font-weight: 500;
  font-size: .32rem;
  line-height: .48rem;
  color: #000;
  word-break: break-all;
} 
.series_container .desbox  .des_flex{
  display: flex;
  /* align-items: center; */
}
.series_container .desbox .des_flex .des{
  flex:1;
  font-size: .28rem;
  line-height: .44rem;
  color: #999999;
  word-break: break-all;
} 
.series_container .desbox .des_flex .showFlag{
  overflow:hidden;
  text-overflow:ellipsis;
  white-space: nowrap;
  /* display:-webkit-box; 
  -webkit-box-orient:vertical;  
  -webkit-line-clamp:1; */
}
.series_container .desbox .des_flex .btn{
  width: .40rem;
  height: .28rem;
  background: url('../../assets/arrow_down.png')  center right no-repeat;
  background-size: .28rem .28rem;
  margin-top: .1rem;
}
.series_container .desbox .des_flex .showbtn{
  background: url('../../assets/arrow_up.png')  center right no-repeat;
  background-size: .28rem .28rem;
}
.series_container .series_main{
 background-color: #fff;
}
.series_container .series_main .tab  .tab_btn .border{
  width: .32rem;
  height: 0px;
  border: 0.02rem solid #EFEFEF;
  transform: rotate(90deg);
  position: absolute;
  right: -.16rem;
}
.series_container .series_main .tab{
  display: flex;
  height: 1rem;
  box-sizing: border-box;
  /* border-bottom: 0.01rem solid #EFEFEF; */
}
.series_container .tabfix{
  position: fixed;
  top: .88rem;
  width: 100%;
  background-color: #FFFFFF;
  z-index: 999;
}
.series_container .tabfix1{
  position: fixed;
  top: 0;
  width: 100%;
  background-color: #FFFFFF;
  z-index: 999;
}
.series_container .mainfix{
  padding-top: 1rem;
}
.series_container .series_main .tab .tab_btn{
  flex: 1;
  font-size: .28rem;
  line-height: .48rem;
  color: #151515;
  border-radius: .08rem;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
}
.series_container .series_main .tab .tabActive{
  color: #FF0095;
  font-weight: bold;
}
.series_container .series_detail{
  padding:0.24rem;
  min-height: 4.82rem;
}
.series_container .series_detail img{
  max-width: 100%;
  max-height: 100%;
}
.series_container .series_main .ser_list{
 padding: 0 .2rem;
}
.series_container .series_main .ser_item{
  padding: .32rem 0;
  border-bottom:.01rem solid #efefef ;
  display: flex;
}
.series_container .series_main .ser_item .lef{
  width: 2.16rem;
  height: 1.62rem;
  margin-right: .2rem;
  display: -webkit-box;
  -webkit-box-pack: center;
  -webkit-box-align: center;
  overflow: hidden;
  position: relative;
  border-radius: .08rem;
}
.series_container .series_main .ser_item .lef .lef_img{
  max-width: 100%;
  height: 100%;
}
.series_container .series_main .ser_item .rig{
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}
.series_container .series_main .ser_item .rig .rigtitle{
  font-weight: 500;
  font-size: .28rem;
  width: 4.2rem;
  line-height: .44rem;
  color: #151515;
  overflow:hidden;
  text-overflow:ellipsis;
  white-space: nowrap;
}

四、展示效果

五、白屏问题

以上代码经过测试在ios部分手机滑的快是切换存在白屏可能

换了一种写法

  onMounted(() => {
      window.addEventListener('scroll', changeScroll, false)
    })
    onUnmounted(() => {
        window.removeEventListener("scroll", changeScroll);
    });
去掉了templete写的滚动事件 @scroll="changeScroll",在事件委托中添加changeScroll事件,方法不变
在css中 添加  min-height: 100vh;

新增判断微信或者ios方法

/* 是否微信环境 */
export function wxEnv() {
    let ua = window.navigator.userAgent.toLowerCase();
    return ua.match(/MicroMessenger/i) == "micromessenger";
}

/* 是否ios终端 */
export function isIOS() {
    let u = navigator.userAgent;
    return !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值