u-list.vue
5.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
<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 值应为某子元素id(id不能以数字开头)
* @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>