index.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. import { VantComponent } from '../common/component';
  2. import { nextTick } from '../common/utils';
  3. VantComponent({
  4. props: {
  5. zIndex: {
  6. type: Number,
  7. value: 99
  8. },
  9. offsetTop: {
  10. type: Number,
  11. value: 0
  12. }
  13. },
  14. data: {
  15. position: '',
  16. height: 0,
  17. wrapStyle: '',
  18. containerStyle: ''
  19. },
  20. methods: {
  21. setWrapStyle() {
  22. const { offsetTop, position } = this.data;
  23. let wrapStyle;
  24. let containerStyle;
  25. switch (position) {
  26. case 'top':
  27. wrapStyle = `
  28. top: ${offsetTop}px;
  29. position: fixed;
  30. `;
  31. containerStyle = `height: ${this.itemHeight}px;`;
  32. break;
  33. case 'bottom':
  34. wrapStyle = `
  35. top: auto;
  36. bottom: 0;
  37. `;
  38. containerStyle = '';
  39. break;
  40. default:
  41. wrapStyle = '';
  42. containerStyle = '';
  43. }
  44. const data = {};
  45. if (wrapStyle !== this.data.wrapStyle) {
  46. data.wrapStyle = wrapStyle;
  47. }
  48. if (containerStyle !== this.data.containerStyle) {
  49. data.containerStyle = containerStyle;
  50. }
  51. if (JSON.stringify(data) !== '{}') {
  52. this.setData(data);
  53. }
  54. },
  55. setPosition(position) {
  56. if (position !== this.data.position) {
  57. this.setData({ position });
  58. nextTick(() => {
  59. this.setWrapStyle();
  60. });
  61. }
  62. },
  63. observerContentScroll() {
  64. const { offsetTop = 0 } = this.data;
  65. const { windowHeight } = wx.getSystemInfoSync();
  66. this.createIntersectionObserver({}).disconnect();
  67. // @ts-ignore
  68. this.createIntersectionObserver()
  69. .relativeToViewport({ top: -(this.itemHeight + offsetTop) })
  70. .observe('.van-sticky', (res) => {
  71. const { top } = res.boundingClientRect;
  72. if (top > offsetTop) {
  73. return;
  74. }
  75. const position = 'top';
  76. this.$emit('scroll', {
  77. scrollTop: top + offsetTop,
  78. isFixed: true
  79. });
  80. this.setPosition(position);
  81. });
  82. // @ts-ignore
  83. this.createIntersectionObserver()
  84. .relativeToViewport({ bottom: -(windowHeight - 1 - offsetTop) })
  85. .observe('.van-sticky', (res) => {
  86. const { top, bottom } = res.boundingClientRect;
  87. if (bottom <= this.itemHeight - 1) {
  88. return;
  89. }
  90. const position = res.intersectionRatio > 0 ? 'top' : '';
  91. this.$emit('scroll', {
  92. scrollTop: top + offsetTop,
  93. isFixed: position === 'top'
  94. });
  95. this.setPosition(position);
  96. });
  97. }
  98. },
  99. mounted() {
  100. this.getRect('.van-sticky').then((rect) => {
  101. this.itemHeight = rect.height;
  102. this.itemTop = rect.top;
  103. this.observerContentScroll();
  104. });
  105. },
  106. destroyed() {
  107. this.createIntersectionObserver({}).disconnect();
  108. }
  109. });