sticky.vue 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <template>
  2. <view class="tui-sticky-class">
  3. <!--sticky 容器-->
  4. <view :style="{height: stickyHeight,background:bgColor}" v-if="isFixed"></view>
  5. <view :class="{'tui-sticky-fixed':isFixed}" :style="{top:isFixed?stickyTop+'px':'auto'}">
  6. <slot name="header"></slot>
  7. </view>
  8. <!--sticky 容器-->
  9. <!--内容-->
  10. <slot name="content"></slot>
  11. </view>
  12. </template>
  13. <script>
  14. export default {
  15. name: "tuiSticky",
  16. props: {
  17. scrollTop: {
  18. type: Number
  19. },
  20. //吸顶容器距离顶部距离 px
  21. stickyTop: {
  22. type: [Number, String]
  23. // #ifdef APP-PLUS || MP
  24. ,
  25. default: 0
  26. // #endif
  27. // #ifdef H5
  28. ,
  29. default: 44
  30. // #endif
  31. },
  32. //吸顶容器 高度 rpx
  33. stickyHeight: {
  34. type: String,
  35. default: "auto"
  36. },
  37. //占位容器背景颜色
  38. bgColor: {
  39. type: String,
  40. default: "none"
  41. },
  42. //列表中的索引值
  43. index: {
  44. type: [Number, String],
  45. default: 0
  46. }
  47. },
  48. watch: {
  49. scrollTop(newValue, oldValue) {
  50. this.updateStickyChange();
  51. }
  52. },
  53. // #ifdef H5
  54. mounted() {
  55. this.updateScrollChange();
  56. },
  57. // #endif
  58. onReady() {
  59. this.updateScrollChange();
  60. },
  61. data() {
  62. return {
  63. timer: null,
  64. top: 0,
  65. height: 0,
  66. isFixed: false
  67. };
  68. },
  69. methods: {
  70. updateStickyChange() {
  71. const top = this.top;
  72. const height = this.height;
  73. const scrollTop = this.scrollTop
  74. let stickyTop = this.stickyTop
  75. // #ifdef H5
  76. stickyTop = stickyTop - 44
  77. stickyTop = stickyTop < 0 ? 0 : stickyTop
  78. // #endif
  79. this.isFixed = (scrollTop + stickyTop >= top && scrollTop + stickyTop < top + height) ? true : false
  80. },
  81. updateScrollChange() {
  82. if (this.timer) {
  83. clearTimeout(this.timer)
  84. this.timer = null
  85. }
  86. this.timer = setTimeout(() => {
  87. const className = '.tui-sticky-class';
  88. const query = uni.createSelectorQuery().in(this);
  89. query.select(className).boundingClientRect((res) => {
  90. if (res) {
  91. this.top = res.top + (this.scrollTop || 0);
  92. this.height = res.height
  93. this.$emit("change", {
  94. index: Number(this.index),
  95. top: this.top
  96. })
  97. }
  98. }).exec()
  99. }, 0)
  100. }
  101. }
  102. }
  103. </script>
  104. <style>
  105. .tui-sticky-fixed {
  106. width: 100%;
  107. position: fixed;
  108. z-index: 99999;
  109. }
  110. </style>