提交 65688b65 编写于 作者: fxy060608's avatar fxy060608

refactor(v3): createIntersectionObserver

上级 d223e34c
...@@ -7172,11 +7172,11 @@ var serviceContext = (function () { ...@@ -7172,11 +7172,11 @@ var serviceContext = (function () {
const requestComponentInfoCallbacks = createCallbacks('requestComponentInfo'); const requestComponentInfoCallbacks = createCallbacks('requestComponentInfo');
function requestComponentInfo (pageInstance, queue, callback) { function requestComponentInfo (pageVm, queue, callback) {
UniServiceJSBridge.publishHandler('requestComponentInfo', { UniServiceJSBridge.publishHandler('requestComponentInfo', {
reqId: requestComponentInfoCallbacks.push(callback), reqId: requestComponentInfoCallbacks.push(callback),
reqs: queue reqs: queue
}, pageInstance.$page.id); }, pageVm.$page.id);
} }
function parseDataset (attr) { function parseDataset (attr) {
...@@ -7245,13 +7245,12 @@ var serviceContext = (function () { ...@@ -7245,13 +7245,12 @@ var serviceContext = (function () {
}); });
} }
function requestComponentInfo$1 (pageInstance, queue, callback) { function requestComponentInfo$1 (pageVm, queue, callback) {
// TODO 重构,逻辑不对,queue 里的每一项可能有单独的作用域查找(即 component) // TODO 重构,逻辑不对,queue 里的每一项可能有单独的作用域查找(即 component)
const vm = pageInstance.$vm; const dom = pageVm._$weex.requireModule('dom');
const dom = vm._$weex.requireModule('dom');
const selectors = getSelectors(queue); const selectors = getSelectors(queue);
let outAttrs = new Array(selectors.length); let outAttrs = new Array(selectors.length);
findAttrs(selectors, vm.$el, outAttrs); findAttrs(selectors, pageVm.$el, outAttrs);
getComponentRectAll(dom, outAttrs, 0, [], (result) => { getComponentRectAll(dom, outAttrs, 0, [], (result) => {
callback(result); callback(result);
}); });
...@@ -8608,6 +8607,76 @@ var serviceContext = (function () { ...@@ -8608,6 +8607,76 @@ var serviceContext = (function () {
createAnimation: createAnimation createAnimation: createAnimation
}); });
const createIntersectionObserverCallbacks = createCallbacks('requestComponentObserver');
const defaultOptions = {
thresholds: [0],
initialRatio: 0,
observeAll: false
};
class ServiceIntersectionObserver {
constructor (pageId, component, options) {
this.pageId = pageId;
this.component = component._$id || component; // app-plus 平台传输_$id
this.options = Object.assign({}, defaultOptions, options);
}
_makeRootMargin (margins = {}) {
this.options.rootMargin = ['top', 'right', 'bottom', 'left'].map(name => `${Number(margins[name]) || 0}px`).join(
' ');
}
relativeTo (selector, margins) {
this.options.relativeToSelector = selector;
this._makeRootMargin(margins);
return this
}
relativeToViewport (margins) {
this.options.relativeToSelector = null;
this._makeRootMargin(margins);
return this
}
observe (selector, callback) {
if (typeof callback !== 'function') {
return
}
this.options.selector = selector;
this.reqId = createIntersectionObserverCallbacks.push(callback);
UniServiceJSBridge.publishHandler('requestComponentObserver', {
reqId: this.reqId,
component: this.component,
options: this.options
}, this.pageId);
}
disconnect () {
UniServiceJSBridge.publishHandler('destroyComponentObserver', {
reqId: this.reqId
}, this.pageId);
}
}
function createIntersectionObserver (context, options) {
if (!context._isVue) {
options = context;
context = null;
}
if (context) {
return new ServiceIntersectionObserver(context.$page.id, context, options)
}
const pages = getCurrentPages();
const len = pages.length;
if (!len) {
UniServiceJSBridge.emit('onError', 'createIntersectionObserver:fail');
}
const page = pages[len - 1];
return new ServiceIntersectionObserver(page.$page.id, page.$vm, options)
}
var require_context_module_1_17 = /*#__PURE__*/Object.freeze({
createIntersectionObserver: createIntersectionObserver
});
class NodesRef { class NodesRef {
constructor (selectorQuery, component, selector, single) { constructor (selectorQuery, component, selector, single) {
this._selectorQuery = selectorQuery; this._selectorQuery = selectorQuery;
...@@ -8714,10 +8783,10 @@ var serviceContext = (function () { ...@@ -8714,10 +8783,10 @@ var serviceContext = (function () {
if (!len) { if (!len) {
UniServiceJSBridge.emit('onError', 'createSelectorQuery:fail'); UniServiceJSBridge.emit('onError', 'createSelectorQuery:fail');
} }
return new SelectorQuery(pages[len - 1]) return new SelectorQuery(pages[len - 1].$vm)
} }
var require_context_module_1_17 = /*#__PURE__*/Object.freeze({ var require_context_module_1_18 = /*#__PURE__*/Object.freeze({
createSelectorQuery: createSelectorQuery createSelectorQuery: createSelectorQuery
}); });
...@@ -8733,7 +8802,7 @@ var serviceContext = (function () { ...@@ -8733,7 +8802,7 @@ var serviceContext = (function () {
callbacks$8.push(callbackId); callbacks$8.push(callbackId);
} }
var require_context_module_1_18 = /*#__PURE__*/Object.freeze({ var require_context_module_1_19 = /*#__PURE__*/Object.freeze({
onKeyboardHeightChange: onKeyboardHeightChange onKeyboardHeightChange: onKeyboardHeightChange
}); });
...@@ -8745,7 +8814,7 @@ var serviceContext = (function () { ...@@ -8745,7 +8814,7 @@ var serviceContext = (function () {
return {} return {}
} }
var require_context_module_1_19 = /*#__PURE__*/Object.freeze({ var require_context_module_1_20 = /*#__PURE__*/Object.freeze({
pageScrollTo: pageScrollTo$1 pageScrollTo: pageScrollTo$1
}); });
...@@ -8781,7 +8850,7 @@ var serviceContext = (function () { ...@@ -8781,7 +8850,7 @@ var serviceContext = (function () {
callbacks$9.push(callbackId); callbacks$9.push(callbackId);
} }
var require_context_module_1_20 = /*#__PURE__*/Object.freeze({ var require_context_module_1_21 = /*#__PURE__*/Object.freeze({
removeTabBarBadge: removeTabBarBadge$1, removeTabBarBadge: removeTabBarBadge$1,
showTabBarRedDot: showTabBarRedDot$1, showTabBarRedDot: showTabBarRedDot$1,
hideTabBarRedDot: hideTabBarRedDot$1, hideTabBarRedDot: hideTabBarRedDot$1,
...@@ -8804,7 +8873,7 @@ var serviceContext = (function () { ...@@ -8804,7 +8873,7 @@ var serviceContext = (function () {
callbacks$a.splice(callbacks$a.indexOf(callbackId), 1); callbacks$a.splice(callbacks$a.indexOf(callbackId), 1);
} }
var require_context_module_1_21 = /*#__PURE__*/Object.freeze({ var require_context_module_1_22 = /*#__PURE__*/Object.freeze({
onWindowResize: onWindowResize, onWindowResize: onWindowResize,
offWindowResize: offWindowResize offWindowResize: offWindowResize
}); });
...@@ -8831,11 +8900,12 @@ var serviceContext = (function () { ...@@ -8831,11 +8900,12 @@ var serviceContext = (function () {
'./network/upload-file.js': require_context_module_1_14, './network/upload-file.js': require_context_module_1_14,
'./storage/storage.js': require_context_module_1_15, './storage/storage.js': require_context_module_1_15,
'./ui/create-animation.js': require_context_module_1_16, './ui/create-animation.js': require_context_module_1_16,
'./ui/create-selector-query.js': require_context_module_1_17, './ui/create-intersection-observer.js': require_context_module_1_17,
'./ui/keyboard.js': require_context_module_1_18, './ui/create-selector-query.js': require_context_module_1_18,
'./ui/page-scroll-to.js': require_context_module_1_19, './ui/keyboard.js': require_context_module_1_19,
'./ui/tab-bar.js': require_context_module_1_20, './ui/page-scroll-to.js': require_context_module_1_20,
'./ui/window.js': require_context_module_1_21, './ui/tab-bar.js': require_context_module_1_21,
'./ui/window.js': require_context_module_1_22,
}; };
var req = function req(key) { var req = function req(key) {
...@@ -9819,6 +9889,12 @@ var serviceContext = (function () { ...@@ -9819,6 +9889,12 @@ var serviceContext = (function () {
initData(Vue); initData(Vue);
initLifecycle(Vue); initLifecycle(Vue);
Object.defineProperty(Vue.prototype, '$page', {
get () {
return this.$root.$scope.$page
}
});
const oldMount = Vue.prototype.$mount; const oldMount = Vue.prototype.$mount;
Vue.prototype.$mount = function mount (el, hydrating) { Vue.prototype.$mount = function mount (el, hydrating) {
if (this.mpType === 'app') { if (this.mpType === 'app') {
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
"strip-json-comments": "^2.0.1" "strip-json-comments": "^2.0.1"
}, },
"uni-app": { "uni-app": {
"compilerVersion": "2.3.3" "compilerVersion": "2.3.4"
}, },
"gitHead": "10184426b19cb76e01c93fb25c982c72887557e8" "gitHead": "10184426b19cb76e01c93fb25c982c72887557e8"
} }
import Vue from 'vue' import createCallbacks from 'uni-helpers/callbacks'
import createCallbacks from 'uni-helpers/callbacks'
const createIntersectionObserverCallbacks = createCallbacks('requestComponentObserver')
const createIntersectionObserverCallbacks = createCallbacks('requestComponentObserver')
const defaultOptions = {
const defaultOptions = { thresholds: [0],
thresholds: [0], initialRatio: 0,
initialRatio: 0, observeAll: false
observeAll: false }
}
class ServiceIntersectionObserver {
class MPIntersectionObserver { constructor (pageId, component, options) {
constructor (pageId, options) { this.pageId = pageId
this.pageId = pageId this.component = component._$id || component // app-plus 平台传输_$id
this.options = Object.assign({}, defaultOptions, options) this.options = Object.assign({}, defaultOptions, options)
} }
_makeRootMargin (margins = {}) { _makeRootMargin (margins = {}) {
this.options.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.options.relativeToSelector = selector relativeTo (selector, margins) {
this._makeRootMargin(margins) this.options.relativeToSelector = selector
return this this._makeRootMargin(margins)
} return this
relativeToViewport (margins) { }
this.options.relativeToSelector = null relativeToViewport (margins) {
this._makeRootMargin(margins) this.options.relativeToSelector = null
return this this._makeRootMargin(margins)
} return this
observe (selector, callback) { }
if (typeof callback !== 'function') { observe (selector, callback) {
return if (typeof callback !== 'function') {
} return
this.options.selector = selector }
this.options.selector = selector
this.reqId = createIntersectionObserverCallbacks.push(callback)
this.reqId = createIntersectionObserverCallbacks.push(callback)
UniServiceJSBridge.publishHandler('requestComponentObserver', {
reqId: this.reqId, UniServiceJSBridge.publishHandler('requestComponentObserver', {
options: this.options reqId: this.reqId,
}, this.pageId) component: this.component,
} options: this.options
disconnect () { }, this.pageId)
UniServiceJSBridge.publishHandler('destroyComponentObserver', { }
reqId: this.reqId disconnect () {
}, this.pageId) UniServiceJSBridge.publishHandler('destroyComponentObserver', {
} reqId: this.reqId
} }, this.pageId)
}
export function createIntersectionObserver (context, options) { }
if (!(context instanceof Vue)) {
options = context export function createIntersectionObserver (context, options) {
context = null if (!context._isVue) {
} options = context
if (context) { context = null
return new MPIntersectionObserver(context.$page.id, options) }
} if (context) {
const app = getApp() return new ServiceIntersectionObserver(context.$page.id, context, options)
if (app.$route && app.$route.params.__id__) { }
return new MPIntersectionObserver(app.$route.params.__id__, options) const pages = getCurrentPages()
} else { const len = pages.length
UniServiceJSBridge.emit('onError', 'createIntersectionObserver:fail') if (!len) {
} UniServiceJSBridge.emit('onError', 'createIntersectionObserver:fail')
}
const page = pages[len - 1]
return new ServiceIntersectionObserver(page.$page.id, page.$vm, options)
} }
...@@ -111,5 +111,5 @@ export function createSelectorQuery (context) { ...@@ -111,5 +111,5 @@ export function createSelectorQuery (context) {
if (!len) { if (!len) {
UniServiceJSBridge.emit('onError', 'createSelectorQuery:fail') UniServiceJSBridge.emit('onError', 'createSelectorQuery:fail')
} }
return new SelectorQuery(pages[len - 1]) return new SelectorQuery(pages[len - 1].$vm)
} }
...@@ -4,6 +4,10 @@ import { ...@@ -4,6 +4,10 @@ import {
import getWindowOffset from 'uni-platform/helpers/get-window-offset' import getWindowOffset from 'uni-platform/helpers/get-window-offset'
import {
findElm
} from './util'
function getRootInfo (fields) { function getRootInfo (fields) {
const info = {} const info = {}
if (fields.id) { if (fields.id) {
...@@ -73,38 +77,8 @@ function getNodeInfo (el, fields) { ...@@ -73,38 +77,8 @@ function getNodeInfo (el, fields) {
return info return info
} }
function findElm (id, vm) {
if (id === vm._$id) {
return vm
}
const childVms = vm.$children
const len = childVms.length
for (let i = 0; i < len; i++) {
const childVm = findElm(id, childVms[i])
if (childVm) {
return childVm
}
}
}
function getElm (component, pageVm) {
if (!component) {
return pageVm.$el
}
if (__PLATFORM__ === 'app-plus') {
if (typeof component === 'string') {
const componentVm = findElm(component, pageVm)
if (!componentVm) {
throw new Error(`Not Found:Page[${pageVm.$page.id}][${component}]`)
}
return componentVm.$el
}
}
return component.$el
}
function getNodesInfo (pageVm, component, selector, single, fields) { function getNodesInfo (pageVm, component, selector, single, fields) {
const $el = getElm(component, pageVm) const $el = findElm(component, pageVm)
if (single) { if (single) {
const node = $el && ($el.matches(selector) ? $el : $el.querySelector(selector)) const node = $el && ($el.matches(selector) ? $el : $el.querySelector(selector))
if (node) { if (node) {
......
import 'intersection-observer' import 'intersection-observer'
import { import {
normalizeDataset normalizeDataset
} from 'uni-helpers/index' } from 'uni-helpers/index'
function getRect (rect) { import {
return { findElm
bottom: rect.bottom, } from './util'
height: rect.height,
left: rect.left, function getRect (rect) {
right: rect.right, return {
top: rect.top, bottom: rect.bottom,
width: rect.width height: rect.height,
} left: rect.left,
} right: rect.right,
top: rect.top,
const intersectionObservers = {} width: rect.width
}
export function requestComponentObserver ({ }
reqId,
options const intersectionObservers = {}
}, pageId) {
const pages = getCurrentPages() export function requestComponentObserver ({
reqId,
const pageVm = pages.find(page => page.$page.id === pageId) component,
options
if (!pageVm) { }, pageId) {
throw new Error(`Not Found:Page[${pageId}]`) const pages = getCurrentPages()
const page = pages.find(page => page.$page.id === pageId)
if (!page) {
throw new Error(`Not Found:Page[${pageId}]`)
} }
const $el = pageVm.$el const pageVm = page.$vm
const root = options.relativeToSelector ? $el.querySelector(options.relativeToSelector) : null const $el = findElm(component, pageVm)
let intersectionObserver = intersectionObservers[reqId] = new IntersectionObserver((entries, observer) => { const root = options.relativeToSelector ? $el.querySelector(options.relativeToSelector) : null
entries.forEach(entrie => {
UniViewJSBridge.publishHandler('onRequestComponentObserver', { let intersectionObserver = intersectionObservers[reqId] = new IntersectionObserver((entries, observer) => {
reqId, entries.forEach(entrie => {
res: { UniViewJSBridge.publishHandler('onRequestComponentObserver', {
intersectionRatio: entrie.intersectionRatio, reqId,
intersectionRect: getRect(entrie.intersectionRect), res: {
boundingClientRect: getRect(entrie.boundingClientRect), intersectionRatio: entrie.intersectionRatio,
relativeRect: getRect(entrie.rootBounds), intersectionRect: getRect(entrie.intersectionRect),
time: Date.now(), boundingClientRect: getRect(entrie.boundingClientRect),
dataset: normalizeDataset(entrie.target.dataset || {}), relativeRect: getRect(entrie.rootBounds),
id: entrie.target.id time: Date.now(),
} dataset: normalizeDataset(entrie.target.dataset || {}),
}, pageVm.$page.id) id: entrie.target.id
}) }
}, { }, pageVm.$page.id)
root, })
rootMargin: options.rootMargin, }, {
threshold: options.thresholds root,
}) rootMargin: options.rootMargin,
if (options.observeAll) { threshold: options.thresholds
intersectionObserver.USE_MUTATION_OBSERVER = true })
Array.prototype.map.call($el.querySelectorAll(options.selector), el => { if (options.observeAll) {
intersectionObserver.observe(el) intersectionObserver.USE_MUTATION_OBSERVER = true
}) Array.prototype.map.call($el.querySelectorAll(options.selector), el => {
} else { intersectionObserver.observe(el)
intersectionObserver.USE_MUTATION_OBSERVER = false })
intersectionObserver.observe($el.querySelector(options.selector)) } else {
} intersectionObserver.USE_MUTATION_OBSERVER = false
} intersectionObserver.observe($el.querySelector(options.selector))
}
export function destroyComponentObserver ({ reqId }) { }
const intersectionObserver = intersectionObservers[reqId]
if (intersectionObserver) { export function destroyComponentObserver ({
intersectionObserver.disconnect() reqId
UniViewJSBridge.publishHandler('onRequestComponentObserver', { }) {
reqId, const intersectionObserver = intersectionObservers[reqId]
reqEnd: true if (intersectionObserver) {
}) intersectionObserver.disconnect()
} UniViewJSBridge.publishHandler('onRequestComponentObserver', {
reqId,
reqEnd: true
})
}
} }
function findVmById (id, vm) {
if (id === vm._$id) {
return vm
}
const childVms = vm.$children
const len = childVms.length
for (let i = 0; i < len; i++) {
const childVm = findVmById(id, childVms[i])
if (childVm) {
return childVm
}
}
}
export function findElm (component, pageVm) {
if (!component) {
return pageVm.$el
}
if (__PLATFORM__ === 'app-plus') {
if (typeof component === 'string') {
const componentVm = findVmById(component, pageVm)
if (!componentVm) {
throw new Error(`Not Found:Page[${pageVm.$page.id}][${component}]`)
}
return componentVm.$el
}
}
return component.$el
}
...@@ -64,13 +64,12 @@ function getComponentRectAll (dom, attrs, index, result, callback) { ...@@ -64,13 +64,12 @@ function getComponentRectAll (dom, attrs, index, result, callback) {
}) })
} }
export function requestComponentInfo (pageInstance, queue, callback) { export function requestComponentInfo (pageVm, queue, callback) {
// TODO 重构,逻辑不对,queue 里的每一项可能有单独的作用域查找(即 component) // TODO 重构,逻辑不对,queue 里的每一项可能有单独的作用域查找(即 component)
const vm = pageInstance.$vm const dom = pageVm._$weex.requireModule('dom')
const dom = vm._$weex.requireModule('dom')
const selectors = getSelectors(queue) const selectors = getSelectors(queue)
let outAttrs = new Array(selectors.length) let outAttrs = new Array(selectors.length)
findAttrs(selectors, vm.$el, outAttrs) findAttrs(selectors, pageVm.$el, outAttrs)
getComponentRectAll(dom, outAttrs, 0, [], (result) => { getComponentRectAll(dom, outAttrs, 0, [], (result) => {
callback(result) callback(result)
}) })
......
...@@ -19,6 +19,12 @@ export default { ...@@ -19,6 +19,12 @@ export default {
initData(Vue) initData(Vue)
initLifecycle(Vue) initLifecycle(Vue)
Object.defineProperty(Vue.prototype, '$page', {
get () {
return this.$root.$scope.$page
}
})
const oldMount = Vue.prototype.$mount const oldMount = Vue.prototype.$mount
Vue.prototype.$mount = function mount (el, hydrating) { Vue.prototype.$mount = function mount (el, hydrating) {
if (this.mpType === 'app') { if (this.mpType === 'app') {
......
...@@ -2,9 +2,9 @@ import createCallbacks from 'uni-helpers/callbacks' ...@@ -2,9 +2,9 @@ import createCallbacks from 'uni-helpers/callbacks'
const requestComponentInfoCallbacks = createCallbacks('requestComponentInfo') const requestComponentInfoCallbacks = createCallbacks('requestComponentInfo')
export function requestComponentInfo (pageInstance, queue, callback) { export function requestComponentInfo (pageVm, queue, callback) {
UniServiceJSBridge.publishHandler('requestComponentInfo', { UniServiceJSBridge.publishHandler('requestComponentInfo', {
reqId: requestComponentInfoCallbacks.push(callback), reqId: requestComponentInfoCallbacks.push(callback),
reqs: queue reqs: queue
}, pageInstance.$page.id) }, pageVm.$page.id)
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册