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

refactor(v3): createSelectorQuery

上级 a7367daa
...@@ -7140,6 +7140,129 @@ var serviceContext = (function () { ...@@ -7140,6 +7140,129 @@ var serviceContext = (function () {
} }
} }
const callbacks$1 = {};
function createCallbacks (namespace) {
let scopedCallbacks = callbacks$1[namespace];
if (!scopedCallbacks) {
scopedCallbacks = {
id: 1,
callbacks: Object.create(null)
};
callbacks$1[namespace] = scopedCallbacks;
}
return {
get (id) {
return scopedCallbacks.callbacks[id]
},
pop (id) {
const callback = scopedCallbacks.callbacks[id];
if (callback) {
delete scopedCallbacks.callbacks[id];
}
return callback
},
push (callback) {
const id = scopedCallbacks.id++;
scopedCallbacks.callbacks[id] = callback;
return id
}
}
}
const requestComponentInfoCallbacks = createCallbacks('requestComponentInfo');
function requestComponentInfo (pageInstance, queue, callback) {
UniServiceJSBridge.publishHandler('requestComponentInfo', {
reqId: requestComponentInfoCallbacks.push(callback),
reqs: queue
}, pageInstance.$page.id);
}
function parseDataset (attr) {
const dataset = {};
Object.keys(attr || {}).forEach(key => {
if (key.indexOf('data') === 0) {
let str = key.replace('data', '');
str = str.charAt(0).toLowerCase() + str.slice(1);
dataset[str] = attr[key];
}
});
return dataset
}
function findAttrs (ids, elm, result) {
let nodes = elm.children;
if (!Array.isArray(nodes)) {
return false
}
for (let i = 0; i < nodes.length; i++) {
let node = nodes[i];
if (node.attr) {
let index = ids.indexOf(node.attr.id);
if (index >= 0) {
result[index] = {
id: ids[index],
ref: node.ref,
dataset: parseDataset(node.attr)
};
if (ids.length === 1) {
break
}
}
}
if (node.children) {
findAttrs(ids, node, result);
}
}
}
function getSelectors (queue) {
let ids = [];
for (let i = 0; i < queue.length; i++) {
const selector = queue[i].selector;
if (selector.indexOf('#') === 0) {
ids.push(selector.substring(1));
}
}
return ids
}
function getComponentRectAll (dom, attrs, index, result, callback) {
const attr = attrs[index];
dom.getComponentRect(attr.ref, option => {
option.size.id = attr.id;
option.size.dataset = attr.dataset;
result.push(option.size);
index += 1;
if (index < attrs.length) {
getComponentRectAll(dom, attrs, index, result, callback);
} else {
callback(result);
}
});
}
function requestComponentInfo$1 (pageInstance, queue, callback) {
// TODO 重构,逻辑不对,queue 里的每一项可能有单独的作用域查找(即 component)
const vm = pageInstance.$vm;
const dom = vm._$weex.requireModule('dom');
const selectors = getSelectors(queue);
let outAttrs = new Array(selectors.length);
findAttrs(selectors, vm.$el, outAttrs);
getComponentRectAll(dom, outAttrs, 0, [], (result) => {
callback(result);
});
}
function requestComponentInfo$2 (pageInstance, queue, callback) {
pageInstance.$page.meta.isNVue
? requestComponentInfo$1(pageInstance, queue, callback)
: requestComponentInfo(pageInstance, queue, callback);
}
var api = /*#__PURE__*/Object.freeze({ var api = /*#__PURE__*/Object.freeze({
...@@ -7257,7 +7380,8 @@ var serviceContext = (function () { ...@@ -7257,7 +7380,8 @@ var serviceContext = (function () {
setTabBarItem: setTabBarItem$2, setTabBarItem: setTabBarItem$2,
setTabBarStyle: setTabBarStyle$2, setTabBarStyle: setTabBarStyle$2,
hideTabBar: hideTabBar$2, hideTabBar: hideTabBar$2,
showTabBar: showTabBar$2 showTabBar: showTabBar$2,
requestComponentInfo: requestComponentInfo$2
}); });
const Emitter = new Vue(); const Emitter = new Vue();
...@@ -7482,9 +7606,9 @@ var serviceContext = (function () { ...@@ -7482,9 +7606,9 @@ var serviceContext = (function () {
'error', 'error',
'waiting' 'waiting'
]; ];
const callbacks$1 = {}; const callbacks$2 = {};
eventNames$1.forEach(name => { eventNames$1.forEach(name => {
callbacks$1[name] = []; callbacks$2[name] = [];
}); });
const props$1 = [ const props$1 = [
...@@ -7548,7 +7672,7 @@ var serviceContext = (function () { ...@@ -7548,7 +7672,7 @@ var serviceContext = (function () {
errMsg, errMsg,
errCode errCode
}) => { }) => {
callbacks$1[state].forEach(callback => { callbacks$2[state].forEach(callback => {
if (typeof callback === 'function') { if (typeof callback === 'function') {
callback(state === 'error' ? { callback(state === 'error' ? {
errMsg, errMsg,
...@@ -7600,7 +7724,7 @@ var serviceContext = (function () { ...@@ -7600,7 +7724,7 @@ var serviceContext = (function () {
eventNames$1.forEach(item => { eventNames$1.forEach(item => {
const name = item[0].toUpperCase() + item.substr(1); const name = item[0].toUpperCase() + item.substr(1);
BackgroundAudioManager.prototype[`on${name}`] = function (callback) { BackgroundAudioManager.prototype[`on${name}`] = function (callback) {
callbacks$1[item].push(callback); callbacks$2[item].push(callback);
}; };
}); });
...@@ -7614,10 +7738,10 @@ var serviceContext = (function () { ...@@ -7614,10 +7738,10 @@ var serviceContext = (function () {
getBackgroundAudioManager: getBackgroundAudioManager getBackgroundAudioManager: getBackgroundAudioManager
}); });
const callbacks$2 = []; const callbacks$3 = [];
onMethod('onAccelerometerChange', function (res) { onMethod('onAccelerometerChange', function (res) {
callbacks$2.forEach(callbackId => { callbacks$3.forEach(callbackId => {
invoke(callbackId, res); invoke(callbackId, res);
}); });
}); });
...@@ -7629,7 +7753,7 @@ var serviceContext = (function () { ...@@ -7629,7 +7753,7 @@ var serviceContext = (function () {
*/ */
function onAccelerometerChange (callbackId) { function onAccelerometerChange (callbackId) {
// TODO 当没有 start 时,添加 on 需要主动 start? // TODO 当没有 start 时,添加 on 需要主动 start?
callbacks$2.push(callbackId); callbacks$3.push(callbackId);
if (!isEnable) { if (!isEnable) {
startAccelerometer(); startAccelerometer();
} }
...@@ -7684,10 +7808,10 @@ var serviceContext = (function () { ...@@ -7684,10 +7808,10 @@ var serviceContext = (function () {
onBLECharacteristicValueChange: onBLECharacteristicValueChange$1 onBLECharacteristicValueChange: onBLECharacteristicValueChange$1
}); });
const callbacks$3 = []; const callbacks$4 = [];
onMethod('onCompassChange', function (res) { onMethod('onCompassChange', function (res) {
callbacks$3.forEach(callbackId => { callbacks$4.forEach(callbackId => {
invoke(callbackId, res); invoke(callbackId, res);
}); });
}); });
...@@ -7699,7 +7823,7 @@ var serviceContext = (function () { ...@@ -7699,7 +7823,7 @@ var serviceContext = (function () {
*/ */
function onCompassChange (callbackId) { function onCompassChange (callbackId) {
// TODO 当没有 start 时,添加 on 需要主动 start? // TODO 当没有 start 时,添加 on 需要主动 start?
callbacks$3.push(callbackId); callbacks$4.push(callbackId);
if (!isEnable$1) { if (!isEnable$1) {
startCompass(); startCompass();
} }
...@@ -7730,23 +7854,23 @@ var serviceContext = (function () { ...@@ -7730,23 +7854,23 @@ var serviceContext = (function () {
stopCompass: stopCompass stopCompass: stopCompass
}); });
const callbacks$4 = []; const callbacks$5 = [];
onMethod('onNetworkStatusChange', res => { onMethod('onNetworkStatusChange', res => {
callbacks$4.forEach(callbackId => { callbacks$5.forEach(callbackId => {
invoke(callbackId, res); invoke(callbackId, res);
}); });
}); });
function onNetworkStatusChange (callbackId) { function onNetworkStatusChange (callbackId) {
callbacks$4.push(callbackId); callbacks$5.push(callbackId);
} }
var require_context_module_1_9 = /*#__PURE__*/Object.freeze({ var require_context_module_1_9 = /*#__PURE__*/Object.freeze({
onNetworkStatusChange: onNetworkStatusChange onNetworkStatusChange: onNetworkStatusChange
}); });
const callbacks$5 = { const callbacks$6 = {
pause: [], pause: [],
resume: [], resume: [],
start: [], start: [],
...@@ -7760,7 +7884,7 @@ var serviceContext = (function () { ...@@ -7760,7 +7884,7 @@ var serviceContext = (function () {
const state = res.state; const state = res.state;
delete res.state; delete res.state;
delete res.errMsg; delete res.errMsg;
callbacks$5[state].forEach(callback => { callbacks$6[state].forEach(callback => {
if (typeof callback === 'function') { if (typeof callback === 'function') {
callback(res); callback(res);
} }
...@@ -7768,7 +7892,7 @@ var serviceContext = (function () { ...@@ -7768,7 +7892,7 @@ var serviceContext = (function () {
}); });
} }
onError (callback) { onError (callback) {
callbacks$5.error.push(callback); callbacks$6.error.push(callback);
} }
onFrameRecorded (callback) { onFrameRecorded (callback) {
...@@ -7780,16 +7904,16 @@ var serviceContext = (function () { ...@@ -7780,16 +7904,16 @@ var serviceContext = (function () {
} }
onPause (callback) { onPause (callback) {
callbacks$5.pause.push(callback); callbacks$6.pause.push(callback);
} }
onResume (callback) { onResume (callback) {
callbacks$5.resume.push(callback); callbacks$6.resume.push(callback);
} }
onStart (callback) { onStart (callback) {
callbacks$5.start.push(callback); callbacks$6.start.push(callback);
} }
onStop (callback) { onStop (callback) {
callbacks$5.stop.push(callback); callbacks$6.stop.push(callback);
} }
pause () { pause () {
invokeMethod('operateRecorder', { invokeMethod('operateRecorder', {
...@@ -8090,7 +8214,7 @@ var serviceContext = (function () { ...@@ -8090,7 +8214,7 @@ var serviceContext = (function () {
const socketTasks$1 = Object.create(null); const socketTasks$1 = Object.create(null);
const socketTasksArray = []; const socketTasksArray = [];
const callbacks$6 = Object.create(null); const callbacks$7 = Object.create(null);
onMethod('onSocketTaskStateChange', ({ onMethod('onSocketTaskStateChange', ({
socketTaskId, socketTaskId,
state, state,
...@@ -8111,8 +8235,8 @@ var serviceContext = (function () { ...@@ -8111,8 +8235,8 @@ var serviceContext = (function () {
if (state === 'open') { if (state === 'open') {
socketTask.readyState = socketTask.OPEN; socketTask.readyState = socketTask.OPEN;
} }
if (socketTask === socketTasksArray[0] && callbacks$6[state]) { if (socketTask === socketTasksArray[0] && callbacks$7[state]) {
invoke(callbacks$6[state], state === 'message' ? { invoke(callbacks$7[state], state === 'message' ? {
data data
} : {}); } : {});
} }
...@@ -8171,19 +8295,19 @@ var serviceContext = (function () { ...@@ -8171,19 +8295,19 @@ var serviceContext = (function () {
} }
function onSocketOpen (callbackId) { function onSocketOpen (callbackId) {
callbacks$6.open = callbackId; callbacks$7.open = callbackId;
} }
function onSocketError (callbackId) { function onSocketError (callbackId) {
callbacks$6.error = callbackId; callbacks$7.error = callbackId;
} }
function onSocketMessage (callbackId) { function onSocketMessage (callbackId) {
callbacks$6.message = callbackId; callbacks$7.message = callbackId;
} }
function onSocketClose (callbackId) { function onSocketClose (callbackId) {
callbacks$6.close = callbackId; callbacks$7.close = callbackId;
} }
var require_context_module_1_13 = /*#__PURE__*/Object.freeze({ var require_context_module_1_13 = /*#__PURE__*/Object.freeze({
...@@ -8484,19 +8608,132 @@ var serviceContext = (function () { ...@@ -8484,19 +8608,132 @@ var serviceContext = (function () {
createAnimation: createAnimation createAnimation: createAnimation
}); });
const callbacks$7 = []; class NodesRef {
constructor (selectorQuery, component, selector, single) {
this._selectorQuery = selectorQuery;
this._component = component;
this._selector = selector;
this._single = single;
}
boundingClientRect (callback) {
this._selectorQuery._push(
this._selector,
this._component,
this._single, {
id: true,
dataset: true,
rect: true,
size: true
},
callback);
return this._selectorQuery
}
fields (fields, callback) {
this._selectorQuery._push(
this._selector,
this._component,
this._single,
fields,
callback
);
return this._selectorQuery
}
scrollOffset (callback) {
this._selectorQuery._push(
this._selector,
this._component,
this._single, {
id: true,
dataset: true,
scrollOffset: true
},
callback
);
return this._selectorQuery
}
}
class SelectorQuery {
constructor (page) {
this._page = page;
this._queue = [];
this._queueCb = [];
}
exec (callback) {
invokeMethod('requestComponentInfo', this._page, this._queue, res => {
const queueCbs = this._queueCb;
res.forEach((result, index) => {
const queueCb = queueCbs[index];
if (isFn(queueCb)) {
queueCb.call(this, result);
}
});
isFn(callback) && callback.call(this, res);
});
}
['in'] (component) {
// app-plus 平台传递 id
this._component = component._$id || component;
return this
}
select (selector) {
return new NodesRef(this, this._component, selector, true)
}
selectAll (selector) {
return new NodesRef(this, this._component, selector, false)
}
selectViewport () {
return new NodesRef(this, 0, '', true)
}
_push (selector, component, single, fields, callback) {
this._queue.push({
component,
selector,
single,
fields
});
this._queueCb.push(callback);
}
}
function createSelectorQuery (context) {
if (context) {
return new SelectorQuery(context)
}
const pages = getCurrentPages();
const len = pages.length;
if (!len) {
UniServiceJSBridge.emit('onError', 'createSelectorQuery:fail');
}
return new SelectorQuery(pages[len - 1])
}
var require_context_module_1_17 = /*#__PURE__*/Object.freeze({
createSelectorQuery: createSelectorQuery
});
const callbacks$8 = [];
onMethod('onKeyboardHeightChange', res => { onMethod('onKeyboardHeightChange', res => {
callbacks$7.forEach(callbackId => { callbacks$8.forEach(callbackId => {
invoke(callbackId, res); invoke(callbackId, res);
}); });
}); });
function onKeyboardHeightChange (callbackId) { function onKeyboardHeightChange (callbackId) {
callbacks$7.push(callbackId); callbacks$8.push(callbackId);
} }
var require_context_module_1_17 = /*#__PURE__*/Object.freeze({ var require_context_module_1_18 = /*#__PURE__*/Object.freeze({
onKeyboardHeightChange: onKeyboardHeightChange onKeyboardHeightChange: onKeyboardHeightChange
}); });
...@@ -8508,7 +8745,7 @@ var serviceContext = (function () { ...@@ -8508,7 +8745,7 @@ var serviceContext = (function () {
return {} return {}
} }
var require_context_module_1_18 = /*#__PURE__*/Object.freeze({ var require_context_module_1_19 = /*#__PURE__*/Object.freeze({
pageScrollTo: pageScrollTo$1 pageScrollTo: pageScrollTo$1
}); });
...@@ -8532,42 +8769,42 @@ var serviceContext = (function () { ...@@ -8532,42 +8769,42 @@ var serviceContext = (function () {
const hideTabBarRedDot$1 = removeTabBarBadge$1; const hideTabBarRedDot$1 = removeTabBarBadge$1;
const callbacks$8 = []; const callbacks$9 = [];
onMethod('onTabBarMidButtonTap', res => { onMethod('onTabBarMidButtonTap', res => {
callbacks$8.forEach(callbackId => { callbacks$9.forEach(callbackId => {
invoke(callbackId, res); invoke(callbackId, res);
}); });
}); });
function onTabBarMidButtonTap (callbackId) { function onTabBarMidButtonTap (callbackId) {
callbacks$8.push(callbackId); callbacks$9.push(callbackId);
} }
var require_context_module_1_19 = /*#__PURE__*/Object.freeze({ var require_context_module_1_20 = /*#__PURE__*/Object.freeze({
removeTabBarBadge: removeTabBarBadge$1, removeTabBarBadge: removeTabBarBadge$1,
showTabBarRedDot: showTabBarRedDot$1, showTabBarRedDot: showTabBarRedDot$1,
hideTabBarRedDot: hideTabBarRedDot$1, hideTabBarRedDot: hideTabBarRedDot$1,
onTabBarMidButtonTap: onTabBarMidButtonTap onTabBarMidButtonTap: onTabBarMidButtonTap
}); });
const callbacks$9 = []; const callbacks$a = [];
onMethod('onViewDidResize', res => { onMethod('onViewDidResize', res => {
callbacks$9.forEach(callbackId => { callbacks$a.forEach(callbackId => {
invoke(callbackId, res); invoke(callbackId, res);
}); });
}); });
function onWindowResize (callbackId) { function onWindowResize (callbackId) {
callbacks$9.push(callbackId); callbacks$a.push(callbackId);
} }
function offWindowResize (callbackId) { function offWindowResize (callbackId) {
// 此处和微信平台一致查询不到去掉最后一个 // 此处和微信平台一致查询不到去掉最后一个
callbacks$9.splice(callbacks$9.indexOf(callbackId), 1); callbacks$a.splice(callbacks$a.indexOf(callbackId), 1);
} }
var require_context_module_1_20 = /*#__PURE__*/Object.freeze({ var require_context_module_1_21 = /*#__PURE__*/Object.freeze({
onWindowResize: onWindowResize, onWindowResize: onWindowResize,
offWindowResize: offWindowResize offWindowResize: offWindowResize
}); });
...@@ -8594,10 +8831,11 @@ var serviceContext = (function () { ...@@ -8594,10 +8831,11 @@ 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/keyboard.js': require_context_module_1_17, './ui/create-selector-query.js': require_context_module_1_17,
'./ui/page-scroll-to.js': require_context_module_1_18, './ui/keyboard.js': require_context_module_1_18,
'./ui/tab-bar.js': require_context_module_1_19, './ui/page-scroll-to.js': require_context_module_1_19,
'./ui/window.js': require_context_module_1_20, './ui/tab-bar.js': require_context_module_1_20,
'./ui/window.js': require_context_module_1_21,
}; };
var req = function req(key) { var req = function req(key) {
...@@ -8635,10 +8873,10 @@ var serviceContext = (function () { ...@@ -8635,10 +8873,10 @@ var serviceContext = (function () {
pageIds = [pageIds]; pageIds = [pageIds];
} }
const evalJSCode = const evalJSCode =
`typeof UniViewJSBridge !== 'undefined' && UniViewJSBridge.subscribeHandler("${eventType}",${args})`; `typeof UniViewJSBridge !== 'undefined' && UniViewJSBridge.subscribeHandler("${eventType}",${args},__PAGE_ID__)`;
pageIds.forEach(id => { pageIds.forEach(id => {
const webview = plus.webview.getWebviewById(String(id)); const webview = plus.webview.getWebviewById(String(id));
webview && webview.evalJS(evalJSCode); webview && webview.evalJS(evalJSCode.replace('__PAGE_ID__', id));
}); });
} }
...@@ -8750,36 +8988,6 @@ var serviceContext = (function () { ...@@ -8750,36 +8988,6 @@ var serviceContext = (function () {
on('onWebInvokeAppService', onWebInvokeAppService); on('onWebInvokeAppService', onWebInvokeAppService);
} }
const callbacks$a = {};
function createCallbacks (namespace) {
let scopedCallbacks = callbacks$a[namespace];
if (!scopedCallbacks) {
scopedCallbacks = {
id: 1,
callbacks: Object.create(null)
};
callbacks$a[namespace] = scopedCallbacks;
}
return {
get (id) {
return scopedCallbacks.callbacks[id]
},
pop (id) {
const callback = scopedCallbacks.callbacks[id];
if (callback) {
delete scopedCallbacks.callbacks[id];
}
return callback
},
push (callback) {
const id = scopedCallbacks.id++;
scopedCallbacks.callbacks[id] = callback;
return id
}
}
}
function initSubscribe (subscribe, { function initSubscribe (subscribe, {
getApp, getApp,
getCurrentPages getCurrentPages
......
...@@ -9929,7 +9929,8 @@ var handleData = (_handleData = {}, _defineProperty(_handleData, _constants__WEB ...@@ -9929,7 +9929,8 @@ var handleData = (_handleData = {}, _defineProperty(_handleData, _constants__WEB
pageId = _data2[0], pageId = _data2[0],
pagePath = _data2[1]; pagePath = _data2[1];
new PageVueComponent({ var page = getCurrentPages()[0];
page.$vm = new PageVueComponent({
mpType: 'page', mpType: 'page',
pageId: pageId, pageId: pageId,
pagePath: pagePath pagePath: pagePath
...@@ -12615,10 +12616,26 @@ function getNodeInfo(el, fields) { ...@@ -12615,10 +12616,26 @@ function getNodeInfo(el, fields) {
return info; return info;
} }
function getElm(component, pageVm) {
if (!component) {
return pageVm.$el;
}
if (typeof component === 'string') {
var componentVm = pageVm._$vd.getVm(component);
if (!componentVm) {
throw new Error("Not Found\uFF1APage[".concat(pageVm.$page.id, "][").concat(component, "]"));
}
return componentVm.$el;
}
return component.$el;
}
function getNodesInfo(pageVm, component, selector, single, fields) { function getNodesInfo(pageVm, component, selector, single, fields) {
/* eslint-disable no-mixed-operators */ var $el = getElm(component, pageVm);
// TODO 判断 component 是否是 _$id,如果是,从 pageVm 中递归查找该组件实例
var $el = component && component.$el || pageVm.$el;
if (single) { if (single) {
var node = $el && ($el.matches(selector) ? $el : $el.querySelector(selector)); var node = $el && ($el.matches(selector) ? $el : $el.querySelector(selector));
...@@ -12653,15 +12670,15 @@ function requestComponentInfo(_ref, pageId) { ...@@ -12653,15 +12670,15 @@ function requestComponentInfo(_ref, pageId) {
reqs = _ref.reqs; reqs = _ref.reqs;
var pages = getCurrentPages(); // 跨平台时,View 层也应该实现该方法,举例 App 上,View 层的 getCurrentPages 返回长度为1的当前页面数组 var pages = getCurrentPages(); // 跨平台时,View 层也应该实现该方法,举例 App 上,View 层的 getCurrentPages 返回长度为1的当前页面数组
var pageVm = pages.find(function (page) { var page = pages.find(function (page) {
return page.$page.id === pageId; return page.$page.id === pageId;
}); });
if (!pageVm) { if (!page) {
// TODO 是否需要 defer
throw new Error("Not Found\uFF1APage[".concat(pageId, "]")); throw new Error("Not Found\uFF1APage[".concat(pageId, "]"));
} }
var pageVm = page.$vm;
var result = []; var result = [];
reqs.forEach(function (_ref2) { reqs.forEach(function (_ref2) {
var component = _ref2.component, var component = _ref2.component,
......
import { import {
isFn isFn
} from 'uni-shared' } from 'uni-shared'
import {
import createCallbacks from 'uni-helpers/callbacks' invokeMethod
} from '../../platform'
const requestComponentInfoCallbacks = createCallbacks('requestComponentInfo')
class NodesRef { class NodesRef {
constructor (selectorQuery, component, selector, single) { constructor (selectorQuery, component, selector, single) {
...@@ -54,24 +53,15 @@ class NodesRef { ...@@ -54,24 +53,15 @@ class NodesRef {
} }
} }
function requestComponentInfo (pageId, queue, callback) {
const reqId = requestComponentInfoCallbacks.push(callback)
UniServiceJSBridge.publishHandler('requestComponentInfo', {
reqId,
reqs: queue
}, pageId)
}
class SelectorQuery { class SelectorQuery {
constructor (pageId) { constructor (page) {
this.pageId = pageId this._page = page
this._queue = [] this._queue = []
this._queueCb = [] this._queueCb = []
} }
exec (callback) { exec (callback) {
requestComponentInfo(this.pageId, this._queue, res => { invokeMethod('requestComponentInfo', this._page, this._queue, res => {
const queueCbs = this._queueCb const queueCbs = this._queueCb
res.forEach((result, index) => { res.forEach((result, index) => {
const queueCb = queueCbs[index] const queueCb = queueCbs[index]
...@@ -83,9 +73,9 @@ class SelectorQuery { ...@@ -83,9 +73,9 @@ class SelectorQuery {
}) })
} }
['in'] (component) { ['in'] (component) {
// TODO 跨平台,非 h5 平台传递 component._$id // app-plus 平台传递 id
this._component = component this._component = component._$id || component
return this return this
} }
...@@ -114,12 +104,12 @@ class SelectorQuery { ...@@ -114,12 +104,12 @@ class SelectorQuery {
export function createSelectorQuery (context) { export function createSelectorQuery (context) {
if (context) { if (context) {
return new SelectorQuery(context.$page.id) return new SelectorQuery(context)
} }
const app = getApp() const pages = getCurrentPages()
if (app.$route && app.$route.params.__id__) { const len = pages.length
return new SelectorQuery(app.$route.params.__id__) if (!len) {
} else {
UniServiceJSBridge.emit('onError', 'createSelectorQuery:fail') UniServiceJSBridge.emit('onError', 'createSelectorQuery:fail')
} }
return new SelectorQuery(pages[len - 1])
} }
...@@ -73,10 +73,22 @@ function getNodeInfo (el, fields) { ...@@ -73,10 +73,22 @@ function getNodeInfo (el, fields) {
return info return info
} }
function getElm (component, pageVm) {
if (!component) {
return pageVm.$el
}
if (typeof component === 'string') {
const componentVm = pageVm._$vd.getVm(component)
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) {
/* eslint-disable no-mixed-operators */ const $el = getElm(component, pageVm)
// TODO 判断 component 是否是 _$id,如果是,从 pageVm 中递归查找该组件实例
const $el = component && component.$el || pageVm.$el
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) {
...@@ -106,13 +118,14 @@ export function requestComponentInfo ({ ...@@ -106,13 +118,14 @@ export function requestComponentInfo ({
}, pageId) { }, pageId) {
const pages = getCurrentPages() // 跨平台时,View 层也应该实现该方法,举例 App 上,View 层的 getCurrentPages 返回长度为1的当前页面数组 const pages = getCurrentPages() // 跨平台时,View 层也应该实现该方法,举例 App 上,View 层的 getCurrentPages 返回长度为1的当前页面数组
const pageVm = pages.find(page => page.$page.id === pageId) const page = pages.find(page => page.$page.id === pageId)
if (!pageVm) { if (!page) {
// TODO 是否需要 defer
throw new Error(`Not Found:Page[${pageId}]`) throw new Error(`Not Found:Page[${pageId}]`)
} }
const pageVm = page.$vm
const result = [] const result = []
reqs.forEach(function ({ reqs.forEach(function ({
component, component,
......
...@@ -2,4 +2,4 @@ export * from './context/live-pusher' ...@@ -2,4 +2,4 @@ export * from './context/live-pusher'
export * from './context/map' export * from './context/map'
export * from './context/video' export * from './context/video'
export * from './ui/create-selector-query' export * from './ui/request-component-info'
import { function parseDataset (attr) {
isFn const dataset = {}
} from 'uni-shared'
Object.keys(attr || {}).forEach(key => {
class NodesRef { if (key.indexOf('data') === 0) {
constructor (selectorQuery, component, selector, single) { let str = key.replace('data', '')
this._selectorQuery = selectorQuery str = str.charAt(0).toLowerCase() + str.slice(1)
this._component = component dataset[str] = attr[key]
this._selector = selector }
this._single = single })
}
return dataset
boundingClientRect (callback) { }
this._selectorQuery._push(
this._selector, function findAttrs (ids, elm, result) {
this._component, let nodes = elm.children
this._single, { if (!Array.isArray(nodes)) {
id: true, return false
dataset: true, }
rect: true, for (let i = 0; i < nodes.length; i++) {
size: true let node = nodes[i]
}, if (node.attr) {
callback) let index = ids.indexOf(node.attr.id)
return this._selectorQuery if (index >= 0) {
} result[index] = {
id: ids[index],
fields (fields, callback) { ref: node.ref,
this._selectorQuery._push( dataset: parseDataset(node.attr)
this._selector, }
this._component, if (ids.length === 1) {
this._single, break
fields, }
callback }
) }
return this._selectorQuery if (node.children) {
} findAttrs(ids, node, result)
}
scrollOffset (callback) { }
this._selectorQuery._push( }
this._selector,
this._component, function getSelectors (queue) {
this._single, { let ids = []
id: true, for (let i = 0; i < queue.length; i++) {
dataset: true, const selector = queue[i].selector
scrollOffset: true if (selector.indexOf('#') === 0) {
}, ids.push(selector.substring(1))
callback }
) }
return this._selectorQuery return ids
} }
}
function getComponentRectAll (dom, attrs, index, result, callback) {
function processDataset (attr) { const attr = attrs[index]
const dataset = {} dom.getComponentRect(attr.ref, option => {
option.size.id = attr.id
Object.keys(attr || {}).forEach(key => { option.size.dataset = attr.dataset
if (key.indexOf('data') === 0) { result.push(option.size)
let str = key.replace('data', '') index += 1
str = str.charAt(0).toLowerCase() + str.slice(1) if (index < attrs.length) {
dataset[str] = attr[key] getComponentRectAll(dom, attrs, index, result, callback)
} } else {
}) callback(result)
}
return dataset })
} }
function findAttrs (ids, elm, result) { export function requestComponentInfo (pageInstance, queue, callback) {
let nodes = elm.children // TODO 重构,逻辑不对,queue 里的每一项可能有单独的作用域查找(即 component)
if (!Array.isArray(nodes)) { const vm = pageInstance.$vm
return false const dom = vm._$weex.requireModule('dom')
} const selectors = getSelectors(queue)
for (let i = 0; i < nodes.length; i++) { let outAttrs = new Array(selectors.length)
let node = nodes[i] findAttrs(selectors, vm.$el, outAttrs)
if (node.attr) { getComponentRectAll(dom, outAttrs, 0, [], (result) => {
let index = ids.indexOf(node.attr.id) callback(result)
if (index >= 0) { })
result[index] = {
id: ids[index],
ref: node.ref,
dataset: processDataset(node.attr)
}
if (ids.length === 1) {
break
}
}
}
if (node.children) {
findAttrs(ids, node, result)
}
}
}
function getSelectors (queue) {
let ids = []
for (let i = 0; i < queue.length; i++) {
const selector = queue[i].selector
if (selector.indexOf('#') === 0) {
ids.push(selector.substring(1))
}
}
return ids
}
function getComponentRectAll (dom, attrs, index, result, callback) {
const attr = attrs[index]
dom.getComponentRect(attr.ref, option => {
option.size.id = attr.id
option.size.dataset = attr.dataset
result.push(option.size)
index += 1
if (index < attrs.length) {
getComponentRectAll(dom, attrs, index, result, callback)
} else {
callback(result)
}
})
}
function requestComponentInfo (dom, component, queue, callback) {
const selectors = getSelectors(queue)
let outAttrs = new Array(selectors.length)
findAttrs(selectors, component.$el, outAttrs)
getComponentRectAll(dom, outAttrs, 0, [], (result) => {
callback(result)
})
}
class SelectorQuery {
constructor (pageId) {
this.pageId = pageId
this._queue = []
this._queueCb = []
}
exec (callback) {
if (!this._component) {
return
}
this._dom = this._component._$weex.requireModule('dom')
requestComponentInfo(this._dom, this._component, this._queue, res => {
const queueCbs = this._queueCb
res.forEach((result, index) => {
const queueCb = queueCbs[index]
if (isFn(queueCb)) {
queueCb.call(this, result)
}
})
isFn(callback) && callback.call(this, res)
})
}
['in'] (component) {
if (!component) {
return console.warn('uni.createSelectorQuery 必须传入当前 vm 对象(this)')
}
this._component = component
return this
}
select (selector) {
return new NodesRef(this, this._component, selector, true)
}
selectAll (selector) {
return new NodesRef(this, this._component, selector, false)
}
selectViewport () {
return new NodesRef(this, 0, '', true)
}
_push (selector, component, single, fields, callback) {
this._queue.push({
component,
selector,
single,
fields
})
this._queueCb.push(callback)
}
}
export function createSelectorQuery () {
return new SelectorQuery()
} }
...@@ -61,3 +61,5 @@ export { ...@@ -61,3 +61,5 @@ export {
from './ui/pull-down-refresh' from './ui/pull-down-refresh'
export * from './ui/tab-bar' export * from './ui/tab-bar'
export * from './ui/request-component-info'
import {
requestComponentInfo as requestVueComponentInfo
} from 'uni-platforms/h5/service/api/ui/request-component-info'
import {
requestComponentInfo as requestNVueComponentInfo
} from 'uni-platforms/app-plus-nvue/service/api/ui/request-component-info'
export function requestComponentInfo (pageInstance, queue, callback) {
pageInstance.$page.meta.isNVue
? requestNVueComponentInfo(pageInstance, queue, callback)
: requestVueComponentInfo(pageInstance, queue, callback)
}
...@@ -7,9 +7,9 @@ export function publishHandler (eventType, args, pageIds) { ...@@ -7,9 +7,9 @@ export function publishHandler (eventType, args, pageIds) {
pageIds = [pageIds] pageIds = [pageIds]
} }
const evalJSCode = const evalJSCode =
`typeof UniViewJSBridge !== 'undefined' && UniViewJSBridge.subscribeHandler("${eventType}",${args})` `typeof UniViewJSBridge !== 'undefined' && UniViewJSBridge.subscribeHandler("${eventType}",${args},__PAGE_ID__)`
pageIds.forEach(id => { pageIds.forEach(id => {
const webview = plus.webview.getWebviewById(String(id)) const webview = plus.webview.getWebviewById(String(id))
webview && webview.evalJS(evalJSCode) webview && webview.evalJS(evalJSCode.replace('__PAGE_ID__', id))
}) })
} }
...@@ -50,7 +50,8 @@ const handleData = { ...@@ -50,7 +50,8 @@ const handleData = {
}, },
[PAGE_CREATED]: function onPageCreated (data) { [PAGE_CREATED]: function onPageCreated (data) {
const [pageId, pagePath] = data const [pageId, pagePath] = data
new PageVueComponent({ const page = getCurrentPages()[0]
page.$vm = new PageVueComponent({
mpType: 'page', mpType: 'page',
pageId, pageId,
pagePath pagePath
......
import createCallbacks from 'uni-helpers/callbacks'
const requestComponentInfoCallbacks = createCallbacks('requestComponentInfo')
export function requestComponentInfo (pageInstance, queue, callback) {
UniServiceJSBridge.publishHandler('requestComponentInfo', {
reqId: requestComponentInfoCallbacks.push(callback),
reqs: queue
}, pageInstance.$page.id)
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册