小程序获取指定区滚动高度,scrollview的高度
2020-05-31 本文已影响0人
smallzip
在业务中,经常需要用到滚动视图scrollview,特别是使用自定义导航栏的情况下,如果不使用scrollview会导致自定义导航栏被连带滚动上去,所以不得不使用scrollview。scrollview默认是必须要设置高度的,当业务页面多了之后每个也都设置一遍高度既繁琐又重复,这样的情况不得已封装了一个获取scrollview搞的方法,能够实现只获取需要滚动的视图位置高度。
效果1
小程序滚动视图1.gif效果2
小程序滚动视图2.gif效果1代码块
<!--pages/about-us/index.wxml-->
<view class="container">
<!-- 头部导航 -->
<nav-bar name="关于我们" typeBar="2" id="header"></nav-bar>
<view-box ids="{{['#header']}}" isRefresh="{{false}}">
<view class="content">
<view wx:for="{{[1,2,3,4,5,6,6,7,8,9]}}" wx:key="*this" style="height:20vh;width:100vw;text-align:center;background:#f6f4fc;">
{{item}}
</view>
</view>
</view-box>
</view>
效果2代码块
<!--pages/about-us/index.wxml-->
<view class="container">
<!-- 头部导航 -->
<nav-bar name="关于我们" typeBar="2" id="header"></nav-bar>
<view id="desc" style="height:20vh;text-align:center;">
我在上面,占了一些空间
</view>
<!-- 使用滚动视图 -->
<view-box ids="{{['#header','#foot','#desc']}}" bind:bindrefresherrefresh="bindrefresherrefresh" isRefresh="{{true}}">
<view class="content">
<view wx:for="{{[1,2,3,4,5,6,6,7,8,9]}}" wx:key="*this" style="height:20vh;width:100vw;text-align:center;background:#f6f4fc;">
{{item}}
</view>
</view>
</view-box>
<view id="foot" style="height:20vh;text-align:center;">
我是底部,我占了一些空间
</view>
</view>
我们可以看到,效果1中头部的导航头是不动的,然后内容区域实现了滚动,再看效果1的代码块中,并没有看到使用scrollview标签,那它去哪里了呢?
答案就是封装在了view-box里面。view-box标签上可以看到ids属性,里面是一个数组,数组里面对应的是页面中其他的试图块的id名称,我们只需要把其他视图快的id赋值进ids数组里面,就可以得到当前的视图块高度了。
来看看view-box组件
view-box组件有四个自定义属性
属性名称 | 接受参数类型 | 默认值 | 说明 |
---|---|---|---|
ids | Array | [] | 标签id名数组 |
animationTime | Number | 1500 | 下拉刷新执行时间 |
isRefresh | Boolean | true | 是否允许下拉刷新,默认开启 |
isTabBar | Boolean | false | 是否属于主页,即有底部导航栏tabbar的那几个页面 |
view-box组件的核心是getScrollHeight.js
通过wx.createSelectorQuery()方法来获取节点,和节点高度。
getScrollHeight.js代码如下:
/**
* 获取对应视图内容的高度
* @param array - 传来的id数组
*/
const app = getApp()
module.exports = (params, isTabBar) => {
return new Promise((resolve, reject) => {
// 获取设备高度
wx.getSystemInfo({
success: function(res) {
let screenHeight = res.windowHeight
let query = wx.createSelectorQuery();
for (let i of params) {
query.select(i).boundingClientRect();
}
if (isTabBar) {
query.select('#container').boundingClientRect();
}
query.exec((res) => {
// 取出每个对应标签容器的高度
let containerHeight = 0
if (isTabBar) {
containerHeight = res[res.length - 1].height
}
let noScrollHeight = res.reduce((total, item, index) => {
if (isTabBar && index == res.length - 1) return total;
return total + item.height
}, 0)
// 用设备高度做减法
let scrollViewHeight
if (isTabBar) {
scrollViewHeight = containerHeight - noScrollHeight
} else {
scrollViewHeight = screenHeight - noScrollHeight;
}
// 算出来最终滚动条的高度
resolve(scrollViewHeight)
});
}
})
})
}
view-box组件代码如下
// components/view-box/index.js
const getScrollHeight = require('../../utils/getScrollHeight.js')
const app = getApp()
Component({
lifetimes: {
attached: function() {
// 在组件实例进入页面节点树时执行
const ids = this.data.ids
getScrollHeight([...ids], this.data.isTabBar).then(res => {
this.setData({
scrollHeight: res
})
})
},
detached: function() {
// 在组件实例被从页面节点树移除时执行
},
},
/**
* 组件的属性列表
*/
properties: {
ids: {
type: Array,
value: []
},
animationTime: { // 下拉刷新动画时间,默认1500
type: Number,
value: 1500
},
isRefresh: { // 是否允许下拉刷新
type: Boolean,
value: true
},
isTabBar: { // 是否属于主页,即有底部导航栏tabbar的那几个页面
type: Boolean,
value: false
}
},
/**
* 组件的初始数据
*/
data: {
scrollHeight: 0,
refresher: false,
scrollTop: 0
},
/**
* 组件的方法列表
*/
methods: {
// 自定义下拉刷新被触发
bindrefresherrefresh(e) {
this.triggerEvent('bindrefresherrefresh', e)
setTimeout(e => {
this.setData({
refresher: false,
scrollTop: 0
})
}, this.data.animationTime)
}
}
})
<!--components/view-box/index.wxml-->
<scroll-view scroll-y style="width:100vw;height:{{isRefresh?scrollHeight-1:scrollHeight}}px;" refresher-triggered="{{refresher}}" scroll-top="{{scrollTop}}" refresher-enabled bindrefresherrefresh="bindrefresherrefresh">
<view style="width:100vw;height:100%;padding-bottom: {{isRefresh?1:0}}rpx;">
<slot></slot>
</view>
</scroll-view>
如何使用
这个组件是很多页面都需要用得到的,建议放在根目录的app.json里面
组件位置配置好之后,组件的使用有两种场景,一种是在有tabbar的页面中使用,另外一种是在非tabbar页面中使用。
tabbar页面中使用方法
<!--pages/my-order/index.wxml-->
<!-- 这里要注意,需要设置 id="container",只有tabbar页面才需要设置 -->
<view class="container tabbar" id="container">
<!-- 头部导航栏 -->
<nav-bar name="订单" id="navbar" typeBar="3"></nav-bar>
<!-- 内容滚动视图区域,ids是要减去的节点高度, isRefresh是设置可以下拉刷新, isTabBar是设置为tabbar页面,bindrefresherrefresh 是下拉刷新执行的函数,可以在函数内做一些操作,比如重新请求数据 -->
<view-box ids="{{['#navbar']}}" isRefresh="{{true}}" isTabBar="{{true}}" bind:bindrefresherrefresh="bindrefresherrefresh">
<view class="content">
内容
</view>
</view-box>
</view>
非tabbar页面使用方法
<!--pages/about-us/index.wxml-->
<!-- 非tabbar页面不需要设置 id="container" -->
<view class="container">
<!-- 头部导航 -->
<nav-bar name="关于我们" typeBar="2" id="navbar"></nav-bar>
<view-box ids="{{['#navbar']}}" isRefresh="{{false}}">
<view class="content">
非tabbar页面
</view>
</view-box>
</view>