You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
5.0 KiB

2 months ago
<template>
<!-- #ifdef APP-NVUE -->
<list
class="u-list"
:enableBackToTop="enableBackToTop"
:loadmoreoffset="lowerThreshold"
:showScrollbar="showScrollbar"
:style="[listStyle]"
:offset-accuracy="Number(offsetAccuracy)"
@scroll="onScroll"
@loadmore="scrolltolower"
>
<slot />
</list>
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<scroll-view
class="u-list"
:scroll-into-view="scrollIntoView"
:style="[listStyle]"
scroll-y
:scroll-top="Number(scrollTop)"
:lower-threshold="Number(lowerThreshold)"
:upper-threshold="Number(upperThreshold)"
:show-scrollbar="showScrollbar"
:enable-back-to-top="enableBackToTop"
:scroll-with-animation="scrollWithAnimation"
@scroll="onScroll"
@scrolltolower="scrolltolower"
@scrolltoupper="scrolltoupper"
>
<view>
<slot />
</view>
</scroll-view>
<!-- #endif -->
</template>
<script>
import props from './props.js';
// #ifdef APP-NVUE
const dom = uni.requireNativePlugin('dom')
// #endif
/**
* List 列表
* @description 该组件为高性能列表组件
* @tutorial https://www.uviewui.com/components/list.html
* @property {Boolean} showScrollbar 控制是否出现滚动条仅nvue有效 默认 false
* @property {String Number} lowerThreshold 距底部多少时触发scrolltolower事件 默认 50
* @property {String Number} upperThreshold 距顶部多少时触发scrolltoupper事件非nvue有效 默认 0
* @property {String Number} scrollTop 设置竖向滚动条位置默认 0
* @property {String Number} offsetAccuracy 控制 onscroll 事件触发的频率仅nvue有效默认 10
* @property {Boolean} enableFlex 启用 flexbox 布局开启后当前节点声明了display: flex就会成为flex container并作用于其孩子节点仅微信小程序有效默认 false
* @property {Boolean} pagingEnabled 是否按分页模式显示List默认 false
* @property {Boolean} scrollable 是否允许List滚动默认 true
* @property {String} scrollIntoView 值应为某子元素idid不能以数字开头
* @property {Boolean} scrollWithAnimation 在设置滚动条位置时使用动画过渡 默认 false
* @property {Boolean} enableBackToTop iOS点击顶部状态栏安卓双击标题栏时滚动条返回顶部只对微信小程序有效 默认 false
* @property {String Number} height 列表的高度 默认 0
* @property {String Number} width 列表宽度 默认 0
* @property {String Number} preLoadScreen 列表前后预渲染的屏数1代表一个屏幕的高度1.5代表1个半屏幕高度 默认 1
* @property {Object} customStyle 定义需要用到的外部样式
*
* @example <u-list @scrolltolower="scrolltolower"></u-list>
*/
export default {
name: 'u-list',
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
watch: {
scrollIntoView(n) {
this.scrollIntoViewById(n)
}
},
data() {
return {
// 记录内部滚动的距离
innerScrollTop: 0,
// vue下scroll-view在上拉加载时的偏移值
offset: 0,
sys: uni.$u.sys()
}
},
computed: {
listStyle() {
const style = {},
addUnit = uni.$u.addUnit
if (this.width != 0) style.width = addUnit(this.width)
if (this.height != 0) style.height = addUnit(this.height)
// 如果没有定义列表高度,则默认使用屏幕高度
if (!style.height) style.height = addUnit(this.sys.windowHeight, 'px')
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
}
},
provide() {
return {
uList: this
}
},
created() {
this.refs = []
this.children = []
this.anchors = []
},
mounted() {},
methods: {
updateOffsetFromChild(top) {
this.offset = top
},
onScroll(e) {
let scrollTop = 0
// #ifdef APP-NVUE
scrollTop = e.contentOffset.y
// #endif
// #ifndef APP-NVUE
scrollTop = e.detail.scrollTop
// #endif
this.innerScrollTop = scrollTop
this.$emit('scroll', Math.abs(scrollTop))
},
scrollIntoViewById(id) {
// #ifdef APP-NVUE
// 根据id参数找到所有u-list-item中匹配的节点再通过dom模块滚动到对应的位置
const item = this.refs.find(item => item.$refs[id] ? true : false)
dom.scrollToElement(item.$refs[id], {
// 是否需要滚动动画
animated: this.scrollWithAnimation
})
// #endif
},
// 滚动到底部触发事件
scrolltolower(e) {
uni.$u.sleep(30).then(() => {
this.$emit('scrolltolower')
})
},
// #ifndef APP-NVUE
// 滚动到底部时触发非nvue有效
scrolltoupper(e) {
uni.$u.sleep(30).then(() => {
this.$emit('scrolltoupper')
// 这一句很重要能绝对保证在性功能障碍的webview滚动条到顶时取消偏移值让页面置顶
this.offset = 0
})
}
// #endif
},
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-list {
@include flex(column);
}
</style>