u-list.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. <template>
  2. <!-- #ifdef APP-NVUE -->
  3. <list class="u-list" :enableBackToTop="enableBackToTop" :loadmoreoffset="lowerThreshold"
  4. :showScrollbar="showScrollbar" :style="[listStyle]" :offset-accuracy="Number(offsetAccuracy)" @scroll="onScroll"
  5. @loadmore="scrolltolower">
  6. <slot />
  7. </list>
  8. <!-- #endif -->
  9. <!-- #ifndef APP-NVUE -->
  10. <scroll-view class="u-list" :scroll-into-view="scrollIntoView" :style="[listStyle]" scroll-y
  11. :scroll-top="Number(scrollTop)" :lower-threshold="Number(lowerThreshold)"
  12. :upper-threshold="Number(upperThreshold)" :show-scrollbar="showScrollbar" :enable-back-to-top="enableBackToTop"
  13. :scroll-with-animation="scrollWithAnimation" @scroll="onScroll" @scrolltolower="scrolltolower"
  14. @scrolltoupper="scrolltoupper">
  15. <view>
  16. <slot />
  17. </view>
  18. </scroll-view>
  19. <!-- #endif -->
  20. </template>
  21. <script>
  22. import props from './props.js';
  23. // #ifdef APP-NVUE
  24. const dom = uni.requireNativePlugin('dom')
  25. // #endif
  26. /**
  27. * List 列表
  28. * @description 该组件为高性能列表组件
  29. * @tutorial https://www.uviewui.com/components/list.html
  30. * @property {Boolean} showScrollbar 控制是否出现滚动条,仅nvue有效 (默认 false )
  31. * @property {String | Number} lowerThreshold 距底部多少时触发scrolltolower事件 (默认 50 )
  32. * @property {String | Number} upperThreshold 距顶部多少时触发scrolltoupper事件,非nvue有效 (默认 0 )
  33. * @property {String | Number} scrollTop 设置竖向滚动条位置(默认 0 )
  34. * @property {String | Number} offsetAccuracy 控制 onscroll 事件触发的频率,仅nvue有效(默认 10 )
  35. * @property {Boolean} enableFlex 启用 flexbox 布局。开启后,当前节点声明了display: flex就会成为flex container,并作用于其孩子节点,仅微信小程序有效(默认 false )
  36. * @property {Boolean} pagingEnabled 是否按分页模式显示List,(默认 false )
  37. * @property {Boolean} scrollable 是否允许List滚动(默认 true )
  38. * @property {String} scrollIntoView 值应为某子元素id(id不能以数字开头)
  39. * @property {Boolean} scrollWithAnimation 在设置滚动条位置时使用动画过渡 (默认 false )
  40. * @property {Boolean} enableBackToTop iOS点击顶部状态栏、安卓双击标题栏时,滚动条返回顶部,只对微信小程序有效 (默认 false )
  41. * @property {String | Number} height 列表的高度 (默认 0 )
  42. * @property {String | Number} width 列表宽度 (默认 0 )
  43. * @property {String | Number} preLoadScreen 列表前后预渲染的屏数,1代表一个屏幕的高度,1.5代表1个半屏幕高度 (默认 1 )
  44. * @property {Object} customStyle 定义需要用到的外部样式
  45. *
  46. * @example <u-list @scrolltolower="scrolltolower"></u-list>
  47. */
  48. export default {
  49. name: 'u-list',
  50. mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
  51. watch: {
  52. scrollIntoView(n) {
  53. this.scrollIntoViewById(n)
  54. }
  55. },
  56. data() {
  57. return {
  58. // 记录内部滚动的距离
  59. innerScrollTop: 0,
  60. // vue下,scroll-view在上拉加载时的偏移值
  61. offset: 0,
  62. sys: uni.$u.sys()
  63. }
  64. },
  65. computed: {
  66. listStyle() {
  67. const style = {},
  68. addUnit = uni.$u.addUnit
  69. if (this.width != 0) style.width = addUnit(this.width)
  70. if (this.height != 0) style.height = addUnit(this.height)
  71. // 如果没有定义列表高度,则默认使用屏幕高度
  72. if (!style.height) style.height = addUnit(this.sys.windowHeight, 'px')
  73. return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
  74. }
  75. },
  76. provide() {
  77. return {
  78. uList: this
  79. }
  80. },
  81. created() {
  82. this.refs = []
  83. this.children = []
  84. this.anchors = []
  85. },
  86. mounted() {},
  87. methods: {
  88. updateOffsetFromChild(top) {
  89. this.offset = top
  90. },
  91. onScroll(e) {
  92. let scrollTop = 0
  93. // #ifdef APP-NVUE
  94. scrollTop = e.contentOffset.y
  95. // #endif
  96. // #ifndef APP-NVUE
  97. scrollTop = e.detail.scrollTop
  98. // #endif
  99. this.innerScrollTop = scrollTop
  100. this.$emit('scroll', Math.abs(scrollTop))
  101. },
  102. scrollIntoViewById(id) {
  103. // #ifdef APP-NVUE
  104. // 根据id参数,找到所有u-list-item中匹配的节点,再通过dom模块滚动到对应的位置
  105. const item = this.refs.find(item => item.$refs[id] ? true : false)
  106. dom.scrollToElement(item.$refs[id], {
  107. // 是否需要滚动动画
  108. animated: this.scrollWithAnimation
  109. })
  110. // #endif
  111. },
  112. // 滚动到底部触发事件
  113. scrolltolower(e) {
  114. uni.$u.sleep(30).then(() => {
  115. this.$emit('scrolltolower')
  116. })
  117. },
  118. // #ifndef APP-NVUE
  119. // 滚动到底部时触发,非nvue有效
  120. scrolltoupper(e) {
  121. uni.$u.sleep(30).then(() => {
  122. this.$emit('scrolltoupper')
  123. // 这一句很重要,能绝对保证在性功能障碍的webview,滚动条到顶时,取消偏移值,让页面置顶
  124. this.offset = 0
  125. })
  126. }
  127. // #endif
  128. },
  129. }
  130. </script>
  131. <style lang="scss" scoped>
  132. @import "../../libs/css/components.scss";
  133. .u-list {
  134. @include flex(column);
  135. }
  136. </style>