123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183 |
- <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="scrollable"
- :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"
- :refresher-enabled="refresherEnabled"
- :refresher-threshold="refresherThreshold"
- :refresher-default-style="refresherDefaultStyle"
- :refresher-background="refresherBackground"
- :refresher-triggered="refresherTriggered"
- @refresherpulling="refresherpulling"
- @refresherrefresh="refresherrefresh"
- @refresherrestore="refresherrestore"
- @refresherabort="refresherabort"
- :scroll-anchoring="true"
- >
- <view>
- <slot />
- </view>
- </scroll-view>
- <!-- #endif -->
- </template>
- <script>
- import { props } from './props';
- import { mpMixin } from '../../libs/mixin/mpMixin';
- import { mixin } from '../../libs/mixin/mixin';
- import { addUnit, addStyle, deepMerge, sleep, sys } from '../../libs/function/index';
- // #ifdef APP-NVUE
- const dom = uni.requireNativePlugin('dom')
- // #endif
- /**
- * List 列表
- * @description 该组件为高性能列表组件
- * @tutorial https://ijry.github.io/uview-plus/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: [mpMixin, mixin, props],
- watch: {
- scrollIntoView(n) {
- this.scrollIntoViewById(n)
- }
- },
- data() {
- return {
- // 记录内部滚动的距离
- innerScrollTop: 0,
- // vue下,scroll-view在上拉加载时的偏移值
- offset: 0,
- sys: sys()
- }
- },
- computed: {
- listStyle() {
- const style = {};
- 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 deepMerge(style, addStyle(this.customStyle))
- }
- },
- provide() {
- return {
- uList: this
- }
- },
- created() {
- this.refs = []
- this.children = []
- this.anchors = []
- },
- mounted() {},
- emits: ["scroll", "scrolltolower", "scrolltoupper",
- "refresherpulling", "refresherrefresh", "refresherrestore", "refresherabort"],
- 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', 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) {
- sleep(30).then(() => {
- this.$emit('scrolltolower')
- })
- },
- // #ifndef APP-NVUE
- // 滚动到底部时触发,非nvue有效
- scrolltoupper(e) {
- sleep(30).then(() => {
- this.$emit('scrolltoupper')
- // 这一句很重要,能绝对保证在性功能障碍的webview,滚动条到顶时,取消偏移值,让页面置顶
- this.offset = 0
- })
- },
- refresherpulling(e) {
- this.$emit('refresherpulling', e)
- },
- refresherrefresh(e) {
- this.$emit('refresherrefresh', e)
- },
- refresherrestore(e) {
- this.$emit('refresherrestore', e)
- },
- refresherabort(e) {
- this.$emit('refresherabort', e)
- }
- // #endif
- },
- }
- </script>
- <style lang="scss" scoped>
- @import "../../libs/css/components.scss";
- .u-list {
- @include flex(column);
- }
- </style>
|