asia-weex-vue-render4light
Version:
Web renderer for weex project written in Vue DSL.
192 lines (175 loc) • 5.33 kB
JavaScript
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import {
getThrottleLazyload,
watchAppear,
debounce
} from '../utils'
import config from '../config'
const scrollableTypes = config.scrollableTypes
let lazyloadWatched = false
function watchLazyload () {
lazyloadWatched = true
; [
'scroll',
// 'transitionend',
// 'webkitTransitionEnd',
// 'animationend',
// 'webkitAnimationEnd',
'resize'
].forEach(evt => {
window.addEventListener(evt, getThrottleLazyload(25, document.body))
})
/**
* In case the users use the body's overflow to scroll. Then the scroll
* event would not be triggered on the window object but on the body.
*/
document.body.addEventListener('scroll', getThrottleLazyload(25, document.body))
}
let idCnt = 0
let appearWatched = false
/**
* during updating, the appear watcher binding on the appearWatched context
* should be triggered within a debounced wrapper.
* If the updating interval is shorter then 50 ms, then the appear events will
* ignore the change in the previous 50 ms due to the debounce wrapper.
*/
const debouncedWatchAppear = debounce(function () {
watchAppear(appearWatched, true)
}, 50)
/**
* if it's a scrollable tag, then watch appear events for it.
*/
function watchAppearForScrollables (tagName, context) {
// when this is a scroller/list/waterfall
if (scrollableTypes.indexOf(tagName) > -1) {
const sd = context.scrollDirection
if (!sd || sd !== 'horizontal') {
appearWatched = context
watchAppear(context, true)
}
}
}
export default {
beforeCreate () {
if (!lazyloadWatched) {
watchLazyload()
}
},
updated () {
const el = this.$el
if (!el || el.nodeType !== 1) {
return
}
if (this._rootId) {
if (el.className.indexOf('weex-root') <= -1) {
el.classList.add('weex-root')
el.classList.add('weex-ct')
el.setAttribute('data-wx-root-id', this._rootId)
}
}
const tagName = this.$options && this.$options._componentTag
const metaUp = weex._meta.updated
if (!metaUp[tagName]) {
metaUp[tagName] = 0
}
metaUp[tagName]++
// will check appearing when no other changes in latest 50ms.
debouncedWatchAppear()
/**
* since the updating of component may affect the layout, the lazyloading should
* be fired.
*/
this._fireLazyload()
},
mounted () {
const tagName = this.$options && this.$options._componentTag
const el = this.$el
if (!el || el.nodeType !== 1) {
return
}
if (typeof weex._components[tagName] !== 'undefined') {
weex._components[tagName]++
}
const metaMt = weex._meta.mounted
if (!metaMt[tagName]) {
metaMt[tagName] = 0
}
metaMt[tagName]++
watchAppearForScrollables(tagName, this)
// when this is the root element of Vue instance.
if (this === this.$root) {
const rootId = `wx-root-${idCnt++}`
if (!weex._root) {
weex._root = {}
}
weex._root[rootId] = this
this._rootId = rootId
if (el.nodeType !== 1) {
return
}
el.classList.add('weex-root')
el.classList.add('weex-ct')
el.setAttribute('data-wx-root-id', rootId)
/**
* there's no scrollable component in this page. That is to say,
* the page is using body scrolling instead of scrollabe components.
* Then the appear watcher should be attached on the body.
*/
if (!appearWatched) {
appearWatched = this
watchAppear(this, true)
}
this._fireLazyload(el)
}
// give warning for not using $processStyle in vue-loader config.
// if (!warned && !window._style_processing_added) {
// warnProcessStyle()
// }
},
destroyed () {
const el = this.$el
if (!el || el.nodeType !== 1) {
return
}
/**
* if the destroyed element is above another panel with images inside, and the images
* moved into the viewport, then the lazyloading should be triggered.
*/
if (this._rootId) {
delete weex._root[this._rootId]
delete this._rootId
}
const tagName = this.$options && this.$options._componentTag
if (typeof weex._components[tagName] !== 'undefined') {
weex._components[tagName]--
}
const metaDs = weex._meta.destroyed
if (!metaDs[tagName]) {
metaDs[tagName] = 0
}
metaDs[tagName]++
this._fireLazyload()
},
methods: {
_fireLazyload (el) {
getThrottleLazyload(25, el || document.body)()
}
}
}