linfangxing2018 / web

0 stars 0 forks source link

uni-app 小程序中锚点的使用 #3

Open linfangxing2018 opened 3 years ago

linfangxing2018 commented 3 years ago

最近在负责公司微信挂号小程序重构,第一次搞小程序,碰到很多坑,其中有一个功能是这样的,点击tab不同项跳转到页面不同地方(看图就行)。一开始的想法是,进入页面的时候,使用 boundingClientRect() 动态获取那3个元素的高度,点击后再使用scroll-view的scroll-top属性设置滚动条的位置。但是这样做有点缺陷,因为boundingClientRect获取的是元素离页面顶部的距离。它返回的每个点的坐标会随着屏幕滑动而变化。后面想到了锚点,小程序可以通过使用scroll-view的scroll-into-view属性来实现锚点功能。使用scroll-y属性时,必须设置高度。

1629897702353.gif

```html
<div id="imageSlide" @click.stop="scrollIntoView('imageSlide')">商品</div>
<div id="goodsDetail" @click.stop="scrollIntoView('goodsDetail')">详情</div>
<div id="orderDesc" @click.stop="scrollIntoView('orderDesc')">须知</div>

<scroll-view 
   @scroll="scroll" 
   scroll-x="false" 
   :scroll-top="scrollTop" 
   :style="{height: winHeight}"  
   :scroll-into-view="toView"
   :scroll-y="canScroll" 
 >
    <div id="imageSlide">商品</div>   <!-- 需要跳转到的地方,要设置id -->
    <div id="goodsDetail">详情</div>
    <div id="orderDesc">须知</div>
 </scroll-view>
``` 
 ```  js
     data() {
         toView: '', // 锚点名称,点击不同tab
         winHeight: '100%'
     },
     onShow() {
         uni.getSystemInfo({
             success: (res) => { 
                console.log(res.windowHeight); 

                this.winHeight = res.windowHeight*2 - 100 + 'rpx'  // 100rpx为导航栏高度
             }

         })
     }

     scrollIntoView(name) {
        this.toView = name
        if (this.timeout) {
            clearTimeout(this.timeout)
        }
        this.timeout = setTimeout(() => {
            this.toView = ''
        })
     }
```

为了防止滚动页面在点击之前的锚点跳转无效,可以监听滚动事件,滚动时将scroll-into-view属性的值清空,或者在每次锚点跳转后,再由一个异步操作将scroll-into-view属性的值清空。

一些小问题以及优化

       const query = uni.createSelectorQuery().in(this);  
       query.select('#id').boundingClientRect(data => { 
           console.log("得到布局位置信息" + JSON.stringify(data)); 
           console.log("节点离页面顶部的距离为" + data.top); 
       }).exec();

1629900982307.gif