You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by so...@apache.org on 2017/06/16 04:06:00 UTC
[07/20] incubator-weex git commit: * [html5] fix appear events.
* [html5] fix appear events.
Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/d8125036
Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/d8125036
Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/d8125036
Branch: refs/heads/0.14-dev
Commit: d8125036f7dbe9f5ecf1c1060e4676f62c030cfb
Parents: 8b39d07
Author: MrRaindrop <te...@gmail.com>
Authored: Wed Jun 7 11:44:23 2017 +0800
Committer: MrRaindrop <te...@gmail.com>
Committed: Wed Jun 7 11:44:23 2017 +0800
----------------------------------------------------------------------
html5/render/vue/mixins/base.js | 9 +-
html5/render/vue/utils/component.js | 159 +++++++++++++++++++++----------
2 files changed, 117 insertions(+), 51 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/d8125036/html5/render/vue/mixins/base.js
----------------------------------------------------------------------
diff --git a/html5/render/vue/mixins/base.js b/html5/render/vue/mixins/base.js
index a1db14c..ad9fe15 100644
--- a/html5/render/vue/mixins/base.js
+++ b/html5/render/vue/mixins/base.js
@@ -19,6 +19,8 @@
import {
getThrottleLazyload,
watchAppear,
+ triggerAppear,
+ triggerDisappear,
extend
} from '../utils'
@@ -98,7 +100,7 @@ export default {
if (this.$el && (i = j = this.$vnode) && (i = i.data) && (j = j.componentOptions)) {
this.$el.attrs = extend({}, i.attrs, j.propsData)
}
-
+ triggerAppear(this)
watchAppear(this)
},
@@ -112,7 +114,10 @@ export default {
if (process.env.NODE_ENV === 'development') {
tagUpdated()
}
- watchAppear(this)
+ },
+
+ destroyed () {
+ triggerDisappear(this)
},
methods: {
http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/d8125036/html5/render/vue/utils/component.js
----------------------------------------------------------------------
diff --git a/html5/render/vue/utils/component.js b/html5/render/vue/utils/component.js
index c810e8d..f724532 100644
--- a/html5/render/vue/utils/component.js
+++ b/html5/render/vue/utils/component.js
@@ -83,57 +83,118 @@ function triggerEvent (elm, handlers, isShow, dir) {
}
}
+/**
+ * get all event listeners. including v-on binding and ons in config.
+ */
+export function getEventHandlers (context) {
+ const parentListeners = context.$options && context.$options._parentListeners
+ const dataOn = context.$vnode && context.$vnode.data && context.$vnode.data.on
+ const on = extend({}, parentListeners, dataOn)
+ return on
+}
+
+/**
+ * Watch element's visibility to tell whether should trigger a appear/disappear
+ * event in scroll handler.
+ */
export function watchAppear (context) {
- if (!context || !context.$el) return null
- const el = context.$el
- context.$nextTick(() => {
- if ((context.$options && context.$options._parentListeners)
- || (context.$vnode && context.$vnode.data && context.$vnode.data.on)) {
- const on = extend({}, context.$options._parentListeners, context.$vnode.data.on)
- if (on.appear || on.disappear) {
- const scroller = getParentScroller(context)
- let isWindow = false
- let container = window
- if (scroller && scroller.$el) {
- container = scroller.$el
- }
- else {
- isWindow = true
- }
- const visible = isElementVisible(el, isWindow ? document.body : container)
- if (context._visible !== visible) {
- context._visible = visible
- // if the component hasn't appeared for once yet, then it shouldn't trigger
- // a disappear event at all.
- if (context._appearedOnce) {
- triggerEvent(el, on, visible, null)
- }
- else if (visible) {
- context._appearedOnce = true
- triggerEvent(el, on, true, null)
- }
- }
+ const el = context && context.$el
+ if (!el) { return }
+
+ const handlers = getEventHandlers(context)
+ if (!handlers.appear && !handlers.disappear) {
+ return
+ }
+
+ let isWindow = false
+ let container = window
+ const scroller = getParentScroller(context)
+ if (scroller && scroller.$el) {
+ container = scroller.$el
+ }
+ else {
+ isWindow = true
+ }
+
+ // add current vm to the container's appear watch list.
+ if (!container._watchAppearList) {
+ container._watchAppearList = []
+ }
+ container._watchAppearList.push(context)
+ if (container._scrollWatched) { return }
+
+ /**
+ * Code below will only exec once for binding scroll handler for parent container.
+ */
+ container._scrollWatched = true
+ const scrollHandler = throttle(event => {
+ /**
+ * detect scrolling direction.
+ * direction only support up & down yet.
+ * TODO: direction support left & right.
+ */
+ const scrollTop = isWindow ? window.pageYOffset : container.scrollTop
+ const preTop = container._lastScrollTop
+ container._lastScrollTop = scrollTop
+ const dir = scrollTop < preTop
+ ? 'down' : scrollTop > preTop
+ ? 'up' : null
+
+ const watchAppearList = container._watchAppearList || []
+ const len = watchAppearList.length
+ for (let i = 0; i < len; i++) {
+ const vm = watchAppearList[i]
+ const visible = isElementVisible(vm.$el, isWindow ? document.body : container)
+ detectAppear(vm, visible, dir)
+ }
+ }, 25, true)
+ container.addEventListener('scroll', scrollHandler, false)
+}
- let lastScrollTop = container.scrollTop || window.pageYOffset
- // no need to watch the same vComponent again.
- if (!context._scrollWatched) {
- context._scrollWatched = true
- const handler = throttle(event => {
- const visible = isElementVisible(el, isWindow ? document.body : container)
- if (visible !== context._visible) {
- context._visible = visible
- const scrollTop = container.scrollTop || window.pageYOffset
- const dir = scrollTop < lastScrollTop
- ? 'down' : scrollTop > lastScrollTop
- ? 'up' : null
- triggerEvent(el, on, visible, dir)
- lastScrollTop = scrollTop
- }
- }, 25, true)
+/**
+ * trigger a appear event.
+ */
+export function triggerAppear (context, visible) {
+ if (!context || !context.$el) { return }
+ if (!visible) {
+ let container = document.body
+ const scroller = getParentScroller(context)
+ if (scroller && scroller.$el) {
+ container = scroller.$el
+ }
+ const visible = isElementVisible(context.$el, container)
+ }
+ return detectAppear(context, visible)
+}
- container.addEventListener('scroll', handler, false)
- }
- }
+/**
+ * trigger a disappear event.
+ */
+export function triggerDisappear (context) {
+ return detectAppear(context, false)
+}
+
+/**
+ * decide whether to trigger a appear/disappear event.
+ * @param {VueComponent} context
+ * @param {boolean} visible
+ * @param {string} dir
+ */
+export function detectAppear (context, visible, dir = null) {
+ const el = context && context.$el
+ if (!el) { return }
+ const handlers = getEventHandlers(context)
+ if (!handlers[visible ? 'appear' : 'disappear']) { return }
+ /**
+ * if the component hasn't appeared for once yet, then it shouldn't trigger
+ * a disappear event at all.
+ */
+ if (!visible && !context._appearedOnce) { return }
+ if (!context._visible === visible) {
+ if (!context._appearedOnce) {
+ context._appearedOnce = true
}
- })
+ context._visible = visible
+ triggerEvent(el, handlers, visible, dir)
+ }
}