From 84887cae210ee206a62ac36cc8ef3e7f40948e32 Mon Sep 17 00:00:00 2001 From: qiang Date: Tue, 2 Jul 2019 21:46:20 +0800 Subject: [PATCH] =?UTF-8?q?update:=20uni.createIntersectionObserver=20?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E6=94=B9=E4=B8=BA=E5=9C=A8=20view=20?= =?UTF-8?q?=E5=B1=82=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/create-intersection-observer.js | 69 ++++++----------- src/core/service/bridge/subscribe.js | 3 +- src/core/view/bridge/subscribe/index.js | 9 ++- .../subscribe/request-component-observer.js | 76 +++++++++++++++++++ 4 files changed, 109 insertions(+), 48 deletions(-) create mode 100644 src/core/view/bridge/subscribe/request-component-observer.js diff --git a/src/core/service/api/create-intersection-observer.js b/src/core/service/api/create-intersection-observer.js index 474c8747..9d20cd0c 100644 --- a/src/core/service/api/create-intersection-observer.js +++ b/src/core/service/api/create-intersection-observer.js @@ -1,5 +1,7 @@ import Vue from 'vue' -import 'intersection-observer' +import createCallbacks from 'uni-helpers/callbacks' + +const createIntersectionObserverCallbacks = createCallbacks('requestComponentObserver') const defaultOptions = { thresholds: [0], @@ -8,60 +10,38 @@ const defaultOptions = { } class MPIntersectionObserver { - _intersectionObserver - _el - _options - _root = null - _rootMargin = '0' - constructor (context, options) { - this._el = context.$el - this._options = Object.assign({}, defaultOptions, options) + constructor (pageId, options) { + this.pageId = pageId + this.options = Object.assign({}, defaultOptions, options) } _makeRootMargin (margins = {}) { - this._rootMargin = ['top', 'right', 'bottom', 'left'].map(name => `${Number(margins[name]) || 0}px`).join(' ') + this.options.rootMargin = ['top', 'right', 'bottom', 'left'].map(name => `${Number(margins[name]) || 0}px`).join(' ') } relativeTo (selector, margins) { - this._root = this._el.querySelector(selector) + this.options.relativeToSelector = selector this._makeRootMargin(margins) } relativeToViewport (margins) { - this._root = null + this.options.relativeToSelector = null this._makeRootMargin(margins) } observe (selector, callback) { if (typeof callback !== 'function') { return } - let options = { - root: this._root, - rootMargin: this._rootMargin, - threshold: this._options.thresholds - } - let intersectionObserver = this._intersectionObserver = new IntersectionObserver((entries, observer) => { - entries.forEach(entrie => { - callback({ - intersectionRatio: entrie.intersectionRatio, - intersectionRect: entrie.intersectionRect, - boundingClientRect: entrie.boundingClientRect, - relativeRect: entrie.rootBounds, - time: entrie.time, - dataset: entrie.target.dataset, - id: entrie.target.id - }) - }) - }, options) - if (this._options.observeAll) { - intersectionObserver.USE_MUTATION_OBSERVER = true - Array.prototype.map.call(this._el.querySelectorAll(selector), el => { - intersectionObserver.observe(el) - }) - } else { - intersectionObserver.USE_MUTATION_OBSERVER = false - intersectionObserver.observe(this._el.querySelector(selector)) - } + this.options.selector = selector + + this.reqId = createIntersectionObserverCallbacks.push(callback) + + UniServiceJSBridge.publishHandler('requestComponentObserver', { + reqId: this.reqId, + options: this.options + }, this.pageId) } disconnect () { - this._intersectionObserver && this._intersectionObserver.disconnect() + UniServiceJSBridge.publishHandler('destroyComponentObserver', { + reqId: this.reqId + }, this.pageId) } } @@ -71,12 +51,11 @@ export function createIntersectionObserver (context, options) { context = null } if (context) { - return new MPIntersectionObserver(context, options) + return new MPIntersectionObserver(context.$page.id, options) } - const pages = getCurrentPages() - if (pages.length) { - context = pages[pages.length - 1] - return new MPIntersectionObserver(context, options) + const app = getApp() + if (app.$route && app.$route.params.__id__) { + return new MPIntersectionObserver(app.$route.params.__id__, options) } else { UniServiceJSBridge.emit('onError', 'createIntersectionObserver:fail') } diff --git a/src/core/service/bridge/subscribe.js b/src/core/service/bridge/subscribe.js index 73902da1..ddb9a893 100644 --- a/src/core/service/bridge/subscribe.js +++ b/src/core/service/bridge/subscribe.js @@ -39,6 +39,7 @@ function onRequestComponentObserver ({ if (callback) { if (reqEnd) { requestComponentObserverCallbacks.pop(reqId) + return } callback(res) } @@ -51,4 +52,4 @@ export default function initSubscribe (subscribe) { subscribe('onRequestComponentInfo', onRequestComponentInfo) subscribe('onRequestComponentObserver', onRequestComponentObserver) -} +} diff --git a/src/core/view/bridge/subscribe/index.js b/src/core/view/bridge/subscribe/index.js index 3f0f0a0d..bc17bde0 100644 --- a/src/core/view/bridge/subscribe/index.js +++ b/src/core/view/bridge/subscribe/index.js @@ -17,6 +17,8 @@ import { import requestComponentInfo from './request-component-info' +import { requestComponentObserver, destroyComponentObserver } from './request-component-observer' + const passiveOptions = supportsPassive ? { passive: false } : false @@ -40,6 +42,9 @@ export default function initSubscribe (subscribe) { subscribe('pageScrollTo', pageScrollTo) + subscribe('requestComponentObserver', requestComponentObserver) + subscribe('destroyComponentObserver', destroyComponentObserver) + if (__PLATFORM__ === 'h5') { let scrollListener = false let disableScrollListener = false @@ -48,7 +53,7 @@ export default function initSubscribe (subscribe) { updateCssVar(vm) }) - subscribe('onPageShow', vm => { + subscribe('onPageShow', vm => { const pageVm = vm.$parent.$parent if (vm._isMounted) { // 非首次 show 才 update(首次 show 的时候在 onPageLoad 中触发了) @@ -87,4 +92,4 @@ export default function initSubscribe (subscribe) { } }) } -} +} diff --git a/src/core/view/bridge/subscribe/request-component-observer.js b/src/core/view/bridge/subscribe/request-component-observer.js new file mode 100644 index 00000000..3ac21cf0 --- /dev/null +++ b/src/core/view/bridge/subscribe/request-component-observer.js @@ -0,0 +1,76 @@ +import 'intersection-observer' + +import { + normalizeDataset +} from 'uni-helpers' + +function getRect (rect) { + return { + bottom: rect.bottom, + height: rect.height, + left: rect.left, + right: rect.right, + top: rect.top, + width: rect.width + } +} + +const intersectionObservers = {} + +export function requestComponentObserver ({ + reqId, + options +}, pageId) { + const pages = getCurrentPages() + + const pageVm = pages.find(page => page.$page.id === pageId) + + if (!pageVm) { + throw new Error(`Not Found:Page[${pageId}]`) + } + + const $el = pageVm.$el + + const root = options.relativeToSelector ? $el.querySelector(options.relativeToSelector) : null + + let intersectionObserver = intersectionObservers[reqId] = new IntersectionObserver((entries, observer) => { + entries.forEach(entrie => { + UniViewJSBridge.publishHandler('onRequestComponentObserver', { + reqId, + res: { + intersectionRatio: entrie.intersectionRatio, + intersectionRect: getRect(entrie.intersectionRect), + boundingClientRect: getRect(entrie.boundingClientRect), + relativeRect: getRect(entrie.rootBounds), + time: Date.now(), + dataset: normalizeDataset(entrie.target.dataset || {}), + id: entrie.target.id + } + }, pageVm.$page.id) + }) + }, { + root, + rootMargin: options.rootMargin, + threshold: options.thresholds + }) + if (options.observeAll) { + intersectionObserver.USE_MUTATION_OBSERVER = true + Array.prototype.map.call($el.querySelectorAll(options.selector), el => { + intersectionObserver.observe(el) + }) + } else { + intersectionObserver.USE_MUTATION_OBSERVER = false + intersectionObserver.observe($el.querySelector(options.selector)) + } +} + +export function destroyComponentObserver ({ reqId }) { + const intersectionObserver = intersectionObservers[reqId] + if (intersectionObserver) { + intersectionObserver.disconnect() + UniViewJSBridge.publishHandler('onRequestComponentObserver', { + reqId, + reqEnd: true + }) + } +} -- GitLab