diff --git a/src/sticky/index.js b/src/sticky/index.js
index 6379b58ac..f12d2f311 100644
--- a/src/sticky/index.js
+++ b/src/sticky/index.js
@@ -7,11 +7,16 @@ const [createComponent, bem] = createNamespace('sticky');
export default createComponent({
mixins: [
- BindEventMixin(function(bind) {
+ BindEventMixin(function(bind, isBind) {
if (!this.scroller) {
this.scroller = getScroller(this.$el);
}
+ if (this.observer) {
+ const method = isBind ? 'observe' : 'unobserve';
+ this.observer[method](this.$el);
+ }
+
bind(this.scroller, 'scroll', this.onScroll, true);
this.onScroll();
}),
@@ -58,6 +63,21 @@ export default createComponent({
},
},
+ created() {
+ // compatibility: https://caniuse.com/#feat=intersectionobserver
+ if (window.IntersectionObserver) {
+ this.observer = new IntersectionObserver(
+ entries => {
+ // trigger scroll when visibility changed
+ if (entries[0].intersectionRatio > 0) {
+ this.onScroll();
+ }
+ },
+ { root: document.body }
+ );
+ }
+ },
+
methods: {
onScroll() {
if (isHidden(this.$el)) {
diff --git a/src/sticky/test/index.spec.js b/src/sticky/test/index.spec.js
index 2212fff2f..0e23111db 100644
--- a/src/sticky/test/index.spec.js
+++ b/src/sticky/test/index.spec.js
@@ -43,6 +43,22 @@ test('offset-top prop', () => {
mockScrollTop(0);
});
+test('should not trigger scroll event when hidden', () => {
+ const scroll = jest.fn();
+ mount({
+ template: `
+
+ Content
+
+ `,
+ methods: {
+ scroll,
+ },
+ });
+
+ expect(scroll).toHaveBeenCalledTimes(0);
+});
+
test('container prop', () => {
const wrapper = mount({
template: `
@@ -68,3 +84,52 @@ test('container prop', () => {
expect(wrapper).toMatchSnapshot();
mockScrollTop(0);
});
+
+test('trigger scroll when visibility changed', () => {
+ const originIntersectionObserver = window.IntersectionObserver;
+
+ const observe = jest.fn();
+ const unobserve = jest.fn();
+ const scroll = jest.fn();
+
+ let observerCallback;
+
+ window.IntersectionObserver = class IntersectionObserver {
+ constructor(callback) {
+ observerCallback = callback;
+ }
+
+ observe() {
+ observe();
+ }
+
+ unobserve() {
+ unobserve();
+ }
+ };
+
+ const wrapper = mount({
+ template: `
+
+ Content
+
+ `,
+ methods: {
+ scroll,
+ },
+ });
+
+ expect(observe).toHaveBeenCalledTimes(1);
+ expect(scroll).toHaveBeenCalledTimes(1);
+
+ observerCallback([{ intersectionRatio: 1 }]);
+ expect(scroll).toHaveBeenCalledTimes(2);
+
+ observerCallback([{ intersectionRatio: 0 }]);
+ expect(scroll).toHaveBeenCalledTimes(2);
+
+ wrapper.destroy();
+ expect(unobserve).toHaveBeenCalledTimes(1);
+
+ window.IntersectionObserver = originIntersectionObserver;
+});