Skip to content

Commit a4669b2

Browse files
committed
Change the event API, add tests and update README
1 parent 850517d commit a4669b2

File tree

5 files changed

+99
-15
lines changed

5 files changed

+99
-15
lines changed

README.md

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,17 +79,27 @@ This means that it's basically a "decorator". A component which does not output
7979

8080
| Property | Type | Default | Required | Description |
8181
| ---------- | ----------- | ----------------- | -------- | ---------------------------------------- |
82-
| threshold | Array | [0.2] | *no* | [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options) |
82+
| threshold | Array | [0, 0.2] | *no* | [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options) |
8383
| root | HTMLElement | null | *no* | [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options) |
8484
| rootMargin | String | *0px 0px 0px 0px* | *no* | [MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#Intersection_observer_options) |
8585

8686

8787

8888
## Events
8989

90-
| Name | Arguments | Description |
91-
| --------------- | --------- | --------------------------- |
92-
| **intersected** | *none* | Event fired on intersected. |
90+
| Name | Arguments | Description |
91+
| ---------- | ---------------------------------------- | ---------------------------------------- |
92+
| **change** | [*IntersectionObserverEntry*](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry) | Event fired on any inte. |
93+
| **enter** | [*IntersectionObserverEntry*](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry) | Event fired when the element is intersected (visible on the screen) |
94+
| **leave** | [*IntersectionObserverEntry*](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry) | Event fired when the element is *not* intersected (not visible on the screen) |
95+
96+
97+
98+
> The **enter** and **leave** event is sugar, for an often performed operation. You still have to set the threshold to e.g. [0, 0.2] (default). If you leave out "0", it will never call the **leave** event.
99+
100+
101+
102+
The events is compliant with Vue's [event modifiers](https://vuejs.org/v2/guide/events.html#Event-Modifiers). This means that you could add `.once` to the events to make sure you only trigger your event handler once.
93103

94104

95105

__tests__/index.js

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ test('It should mount correctly and add the item to the observers list', async (
4343
expect(vm.$el.textContent).toBe('this is my component')
4444
})
4545

46-
test('It should emit "intersected" event when the component is intersected', async () => {
46+
test('It should emit "enter" event when the component is intersected', async () => {
4747
const mockedIntersect = Object.assign({}, Intersect)
4848
const spy = jest.fn()
4949

5050
const vm = new Vue({
51-
template: `<intersect @intersected="intersected"><div></div></intersect>`,
51+
template: `<intersect @enter="onEnter"><div></div></intersect>`,
5252
components: {Intersect: mockedIntersect},
5353
methods: {
54-
intersected: spy
54+
onEnter: spy
5555
}
5656
}).$mount()
5757

@@ -64,6 +64,52 @@ test('It should emit "intersected" event when the component is intersected', asy
6464
expect(spy).toHaveBeenCalledTimes(1)
6565
})
6666

67+
test('It should emit "leave" event when the component is not intersected', async () => {
68+
const mockedIntersect = Object.assign({}, Intersect)
69+
const spy = jest.fn()
70+
71+
const vm = new Vue({
72+
template: `<intersect @leave="onLeave"><div></div></intersect>`,
73+
components: {Intersect: mockedIntersect},
74+
methods: {
75+
onLeave: spy
76+
}
77+
}).$mount()
78+
79+
await vm.$nextTick()
80+
81+
vm._vnode.componentInstance.observer.cb([{
82+
isIntersecting: false
83+
}])
84+
85+
expect(spy).toHaveBeenCalledTimes(1)
86+
})
87+
88+
test('It should emit "change" on any intersection change', async () => {
89+
const mockedIntersect = Object.assign({}, Intersect)
90+
const spy = jest.fn()
91+
92+
const vm = new Vue({
93+
template: `<intersect @change="onChange"><div></div></intersect>`,
94+
components: {Intersect: mockedIntersect},
95+
methods: {
96+
onChange: spy
97+
}
98+
}).$mount()
99+
100+
await vm.$nextTick()
101+
102+
vm._vnode.componentInstance.observer.cb([{
103+
isIntersecting: false
104+
}])
105+
106+
vm._vnode.componentInstance.observer.cb([{
107+
isIntersecting: true
108+
}])
109+
110+
expect(spy).toHaveBeenCalledTimes(2)
111+
})
112+
67113
test('It should be possible to set the threshold property', async () => {
68114
const mockedIntersect = Object.assign({}, Intersect)
69115
const vm = new Vue({
@@ -135,6 +181,8 @@ test('It should warn when no child component is defined', async () => {
135181

136182
expect(global.console.warn).toHaveBeenCalledTimes(1)
137183
expect(vm._vnode.componentInstance.observer.observables.length).toBe(0)
184+
185+
global.console.warn.mockReset()
138186
})
139187

140188
test('It should warn if more than one child component is defined', async () => {
@@ -148,4 +196,24 @@ test('It should warn if more than one child component is defined', async () => {
148196

149197
expect(global.console.warn).toHaveBeenCalledTimes(1)
150198
expect(vm._vnode.componentInstance.observer.observables.length).toBe(1)
199+
200+
global.console.warn.mockReset()
201+
})
202+
203+
test('It should not warn if Vue.config.silent is set to false', async () => {
204+
require('vue').config.silent = true
205+
206+
global.console.warn = jest.fn()
207+
208+
const vm = new Vue({
209+
template: `<intersect><div></div><div></div></intersect>`,
210+
components: {Intersect}
211+
}).$mount()
212+
213+
await vm.$nextTick()
214+
215+
expect(global.console.warn).toHaveBeenCalledTimes(0)
216+
expect(vm._vnode.componentInstance.observer.observables.length).toBe(1)
217+
218+
global.console.warn.mockReset()
151219
})

dist/index.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ export default {
3636
var _this = this;
3737

3838
this.observer = new IntersectionObserver(function (entries) {
39-
if (entries[0].isIntersecting) {
40-
_this.$emit('intersected');
41-
_this.observer.disconnect();
39+
if (!entries[0].isIntersecting) {
40+
_this.$emit('leave', [entries[0]]);
41+
} else {
42+
_this.$emit('enter', [entries[0]]);
4243
}
44+
45+
_this.$emit('change', [entries[0]]);
4346
}, {
4447
threshold: this.threshold,
4548
root: this.root,

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vue-intersect",
3-
"version": "1.0.2",
3+
"version": "1.1.0",
44
"description": "A Vue component to add intersection-observer to a Vue component or HTML element.",
55
"main": "dist/index.js",
66
"repository": "[email protected]:heavyy/vue-intersect.git",

src/index.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export default {
1313
threshold: {
1414
type: Array,
1515
required: false,
16-
default: () => [0.2]
16+
default: () => [0, 0.2]
1717
},
1818
root: {
1919
type: HTMLElement,
@@ -28,10 +28,13 @@ export default {
2828
},
2929
created () {
3030
this.observer = new IntersectionObserver((entries) => {
31-
if (entries[0].isIntersecting) {
32-
this.$emit('intersected')
33-
this.observer.disconnect()
31+
if (!entries[0].isIntersecting) {
32+
this.$emit('leave', [entries[0]])
33+
} else {
34+
this.$emit('enter', [entries[0]])
3435
}
36+
37+
this.$emit('change', [entries[0]])
3538
}, {
3639
threshold: this.threshold,
3740
root: this.root,

0 commit comments

Comments
 (0)