Skip to content

Commit

Permalink
add: Intersection observer
Browse files Browse the repository at this point in the history
  • Loading branch information
hilongjw committed Aug 31, 2017
1 parent 584e547 commit 5e9e437
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 13 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ new Vue({
|`filter`| the image's listener filter |`{ }`| [Image listener filter](#image-listener-filter) |
|`lazyComponent`| lazyload component | `false` | [Lazy Component](#lazy-component)
| `dispatchEvent`|trigger the dom event|`false`|`Boolean`|
| `observer`|use IntersectionObserver|`false`|`Boolean`|
| `observerOptions`|IntersectionObserver options|{ rootMargin: '0px', threshold: 0.1 }|[IntersectionObserver](#intersectionobserver)|

### Desired Listen Events

Expand Down Expand Up @@ -173,6 +175,24 @@ Vue.use(vueLazy, {
})
```

### IntersectionObserver

use [Intersection Observer](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) to to improve performance of a large number of nodes.

```javascript
Vue.use(vueLazy, {
// set observer to true
observer: true,

// optional
observerOptions: {
rootMargin: '0px',
threshold: 0.1
}
})
```


### Lazy Component

```html
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-lazyload",
"version": "1.0.6",
"version": "1.1.0",
"description": "Vue module for lazy-loading images in your vue.js applications.",
"main": "vue-lazyload.js",
"scripts": {
Expand Down
2 changes: 2 additions & 0 deletions src/lazy-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export default (lazy) => {
},
data () {
return {
el: null,
state: {
loaded: false
},
Expand All @@ -24,6 +25,7 @@ export default (lazy) => {
}
},
mounted () {
this.el = this.$el
lazy.addLazyBox(this)
lazy.lazyLoadHandler()
},
Expand Down
74 changes: 64 additions & 10 deletions src/lazy.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,16 @@ import ReactiveListener from './listener'

const DEFAULT_URL = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
const DEFAULT_EVENTS = ['scroll', 'wheel', 'mousewheel', 'resize', 'animationend', 'transitionend', 'touchmove']
const DEFAULT_OBSERVER_OPTIONS = {
rootMargin: '0px',
threshold: 0.1
}

export default function (Vue) {
return class Lazy {
constructor ({ preLoad, error, preLoadTop, dispatchEvent, loading, attempt, silent, scale, listenEvents, hasbind, filter, adapter }) {
constructor ({ preLoad, error, preLoadTop, dispatchEvent, loading, attempt, silent, scale, listenEvents, hasbind, filter, adapter, observer, observerOptions }) {
this.version = '__VUE_LAZYLOAD_VERSION__'
this.mode = 'event'
this.ListenerQueue = []
this.TargetIndex = 0
this.TargetQueue = []
Expand All @@ -38,18 +43,13 @@ export default function (Vue) {
hasbind: false,
supportWebp: supportWebp(),
filter: filter || {},
adapter: adapter || {}
adapter: adapter || {},
observer: !!observer,
observerOptions: observerOptions || DEFAULT_OBSERVER_OPTIONS
}
this._initEvent()

this.lazyLoadHandler = throttle(() => {
let catIn = false
this.ListenerQueue.forEach(listener => {
if (listener.state.loaded) return
catIn = listener.checkInView()
catIn && listener.load()
})
}, 200)
this.setMode(this.options.observer ? 'observer' : 'event')
}

/**
Expand All @@ -75,6 +75,7 @@ export default function (Vue) {
return list
}


/**
* add lazy component to queue
* @param {Vue} vm lazy component instance
Expand All @@ -84,6 +85,7 @@ export default function (Vue) {
this.ListenerQueue.push(vm)
if (inBrowser) {
this._addListenerTarget(window)
this._observer && this._observer.observe(vm.el)
if (vm.$el && vm.$el.parentNode) {
this._addListenerTarget(vm.$el.parentNode)
}
Expand All @@ -103,6 +105,8 @@ export default function (Vue) {
return Vue.nextTick(this.lazyLoadHandler)
}

this._observer && this._observer.observe(el)

let { src, loading, error } = this._valueFormatter(binding.value)

Vue.nextTick(() => {
Expand Down Expand Up @@ -192,6 +196,23 @@ export default function (Vue) {
}
this._removeListenerTarget(window)
}

setMode (mode) {
this.mode = mode // event or observer
if (mode === 'event') {
this.lazyLoadHandler = throttle(() => {
let catIn = false
this.ListenerQueue.forEach(listener => {
if (listener.state.loaded) return
catIn = listener.checkInView()
catIn && listener.load()
})
}, 200)
} else {
this._initIntersectionObserver()
this.lazyLoadHandler = () => {}
}
}

/**** Private functions ****/

Expand Down Expand Up @@ -281,6 +302,39 @@ export default function (Vue) {
}
}

/**
* init IntersectionObserver
* set mode to observer
* @return
*/
_initIntersectionObserver () {
if (inBrowser && 'IntersectionObserver' in window) {
this._observer = new IntersectionObserver(this._observerHandler.bind(this), this.options.observerOptions)
if (this.ListenerQueue.length) {
this.ListenerQueue.forEach(listener => {
this._observer.observer(listener.el)
})
}
}
}

/**
* init IntersectionObserver
* @return
*/
_observerHandler (entries, observer) {
entries.forEach(entry => {
if (entry.isIntersecting) {
this.ListenerQueue.forEach(listener => {
if (listener.el === entry.target) {
if (listener.state.loaded) return
listener.load()
}

})
}
})
}

/**
* set element attribute with image'url and state
Expand Down
4 changes: 2 additions & 2 deletions vue-lazyload.js

Large diffs are not rendered by default.

0 comments on commit 5e9e437

Please sign in to comment.