u-list.vue 5.2 KB

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