From 34b1303b4c1be4acdf2519805ec07ae4fb51dc2b Mon Sep 17 00:00:00 2001 From: fxy060608 Date: Thu, 24 Feb 2022 14:25:29 +0800 Subject: [PATCH] wip(app-nvue): requestComponentInfo --- packages/shims-vue-runtime.d.ts | 1 + .../uni-app-plus/dist/uni-app-service.es.js | 82 ++++++++++++- .../service/api/ui/requestComponentInfo.ts | 111 +++++++++++++++++- packages/uni-shared/dist/uni-shared.cjs.js | 13 ++ packages/uni-shared/dist/uni-shared.d.ts | 3 + packages/uni-shared/dist/uni-shared.es.js | 14 ++- packages/uni-shared/src/nvue.ts | 13 ++ 7 files changed, 232 insertions(+), 5 deletions(-) diff --git a/packages/shims-vue-runtime.d.ts b/packages/shims-vue-runtime.d.ts index 0aa5b368cd..6631d19d84 100644 --- a/packages/shims-vue-runtime.d.ts +++ b/packages/shims-vue-runtime.d.ts @@ -8,6 +8,7 @@ declare module '@vue/runtime-core' { } // 目前 H5,APP 平台 getCurrentPages 中获取的 page 对象调整为 vm 对象 $getAppWebview?: () => PlusWebviewWebviewObject + $requireNativePlugin?: (name: string) => unknown getOpenerEventChannel: () => EventChannel $page: Page.PageInstance['$page'] $mpType?: 'app' | 'page' diff --git a/packages/uni-app-plus/dist/uni-app-service.es.js b/packages/uni-app-plus/dist/uni-app-service.es.js index 856af52f39..9b39f95f26 100644 --- a/packages/uni-app-plus/dist/uni-app-service.es.js +++ b/packages/uni-app-plus/dist/uni-app-service.es.js @@ -358,6 +358,18 @@ var serviceContext = (function (vue) { }; } + function parseNVueDataset(attr) { + const dataset = {}; + if (attr) { + Object.keys(attr).forEach((key) => { + if (key.indexOf('data-') === 0) { + dataset[key.replace('data-', '')] = attr[key]; + } + }); + } + return dataset; + } + class DOMException extends Error { constructor(message) { super(message); @@ -1351,7 +1363,15 @@ var serviceContext = (function (vue) { }; } - function requestComponentInfo(page, reqs, callback) { + function requestComponentInfo(pageVm, reqs, callback) { + if (pageVm.$page.meta.isNVue) { + requestNVueComponentInfo(pageVm, reqs, callback); + } + else { + requestVueComponentInfo(pageVm, reqs, callback); + } + } + function requestVueComponentInfo(pageVm, reqs, callback) { UniServiceJSBridge.invokeViewMethod('requestComponentInfo', { reqs: reqs.map((req) => { if (req.component) { @@ -1359,7 +1379,65 @@ var serviceContext = (function (vue) { } return req; }), - }, page.$page.id, callback); + }, pageVm.$page.id, callback); + } + function requestNVueComponentInfo(pageVm, reqs, callback) { + const ids = findNVueElementIds(reqs); + const nvueElementInfos = new Array(ids.length); + findNVueElementInfos(ids, pageVm.$el, nvueElementInfos); + findComponentRectAll(pageVm.$requireNativePlugin('dom'), nvueElementInfos, 0, [], (result) => { + callback(result); + }); + } + function findNVueElementIds(reqs) { + const ids = []; + for (let i = 0; i < reqs.length; i++) { + const selector = reqs[i].selector; + if (selector.indexOf('#') === 0) { + ids.push(selector.substring(1)); + } + } + return ids; + } + function findNVueElementInfos(ids, elm, infos) { + const nodes = elm.children; + if (!isArray$1(nodes)) { + return false; + } + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i]; + if (node.attr) { + const index = ids.indexOf(node.attr.id); + if (index >= 0) { + infos[index] = { + id: ids[index], + ref: node.ref, + dataset: parseNVueDataset(node.attr), + }; + if (ids.length === 1) { + break; + } + } + } + if (node.children) { + findNVueElementInfos(ids, node, infos); + } + } + } + function findComponentRectAll(dom, nvueElementInfos, index, result, callback) { + const attr = nvueElementInfos[index]; + dom.getComponentRect(attr.ref, (option) => { + option.size.id = attr.id; + option.size.dataset = attr.dataset; + result.push(option.size); + index += 1; + if (index < nvueElementInfos.length) { + findComponentRectAll(dom, nvueElementInfos, index, result, callback); + } + else { + callback(result); + } + }); } function setCurrentPageMeta(page, options) { diff --git a/packages/uni-app-plus/src/service/api/ui/requestComponentInfo.ts b/packages/uni-app-plus/src/service/api/ui/requestComponentInfo.ts index 48796134a7..609bcb08aa 100644 --- a/packages/uni-app-plus/src/service/api/ui/requestComponentInfo.ts +++ b/packages/uni-app-plus/src/service/api/ui/requestComponentInfo.ts @@ -1,8 +1,22 @@ import { ComponentPublicInstance } from 'vue' +import { isArray } from '@vue/shared' import { SelectorQueryRequest, SelectorQueryNodeInfo } from '@dcloudio/uni-api' +import { NVueElement, parseNVueDataset } from '@dcloudio/uni-shared' export function requestComponentInfo( - page: ComponentPublicInstance, + pageVm: ComponentPublicInstance, + reqs: Array, + callback: (result: Array) => void +) { + if (pageVm.$page.meta.isNVue) { + requestNVueComponentInfo(pageVm, reqs, callback) + } else { + requestVueComponentInfo(pageVm, reqs, callback) + } +} + +function requestVueComponentInfo( + pageVm: ComponentPublicInstance, reqs: Array, callback: (result: Array) => void ) { @@ -16,7 +30,100 @@ export function requestComponentInfo( return req }), }, - page.$page.id, + pageVm.$page.id, callback ) } + +function requestNVueComponentInfo( + pageVm: ComponentPublicInstance, + reqs: Array, + callback: (result: Array) => void +) { + const ids = findNVueElementIds(reqs) + const nvueElementInfos = new Array(ids.length) + findNVueElementInfos(ids, pageVm.$el, nvueElementInfos) + findComponentRectAll( + pageVm.$requireNativePlugin!('dom') as NVueDomModule, + nvueElementInfos, + 0, + [], + (result) => { + callback(result) + } + ) +} + +interface NVueElementInfo { + id: string + ref: string + dataset: Record +} +interface NVueDomModule { + getComponentRect: ( + ref: string, + callback: (res: { size: Record }) => void + ) => void +} + +function findNVueElementIds(reqs: Array) { + const ids = [] + for (let i = 0; i < reqs.length; i++) { + const selector = reqs[i].selector + if (selector.indexOf('#') === 0) { + ids.push(selector.substring(1)) + } + } + return ids +} + +function findNVueElementInfos( + ids: string[], + elm: NVueElement, + infos: NVueElementInfo[] +) { + const nodes = elm.children + if (!isArray(nodes)) { + return false + } + for (let i = 0; i < nodes.length; i++) { + const node = nodes[i] + if (node.attr) { + const index = ids.indexOf(node.attr.id as string) + if (index >= 0) { + infos[index] = { + id: ids[index], + ref: node.ref, + dataset: parseNVueDataset(node.attr), + } + if (ids.length === 1) { + break + } + } + } + if (node.children) { + findNVueElementInfos(ids, node, infos) + } + } +} + +function findComponentRectAll( + dom: NVueDomModule, + nvueElementInfos: NVueElementInfo[], + index: number, + result: Array, + callback: (result: Array) => void +) { + const attr = nvueElementInfos[index] + dom.getComponentRect(attr.ref, (option) => { + option.size.id = attr.id + option.size.dataset = attr.dataset + result.push(option.size) + index += 1 + if (index < nvueElementInfos.length) { + findComponentRectAll(dom, nvueElementInfos, index, result, callback) + } else { + callback(result) + } + }) +} diff --git a/packages/uni-shared/dist/uni-shared.cjs.js b/packages/uni-shared/dist/uni-shared.cjs.js index ff47e2ea97..6a8f0d6a3e 100644 --- a/packages/uni-shared/dist/uni-shared.cjs.js +++ b/packages/uni-shared/dist/uni-shared.cjs.js @@ -685,6 +685,18 @@ function formatH5Log(type, filename, ...args) { console[type].apply(console, [...args, filename]); } +function parseNVueDataset(attr) { + const dataset = {}; + if (attr) { + Object.keys(attr).forEach((key) => { + if (key.indexOf('data-') === 0) { + dataset[key.replace('data-', '')] = attr[key]; + } + }); + } + return dataset; +} + function plusReady(callback) { if (typeof callback !== 'function') { return; @@ -1512,6 +1524,7 @@ exports.normalizeTarget = normalizeTarget; exports.onCreateVueApp = onCreateVueApp; exports.once = once; exports.parseEventName = parseEventName; +exports.parseNVueDataset = parseNVueDataset; exports.parseQuery = parseQuery; exports.parseUrl = parseUrl; exports.passive = passive; diff --git a/packages/uni-shared/dist/uni-shared.d.ts b/packages/uni-shared/dist/uni-shared.d.ts index 5c426dd7f5..b87a6e9305 100644 --- a/packages/uni-shared/dist/uni-shared.d.ts +++ b/packages/uni-shared/dist/uni-shared.d.ts @@ -354,6 +354,7 @@ export declare interface NVueElement { type: string; ref: string; text?: string; + attr: Record; styleSheet: Record>>; classList: string[]; parentNode: NVueElement | null; @@ -528,6 +529,8 @@ export declare type PageUpdateAction = CreateAction | InsertAction | RemoveActio export declare function parseEventName(name: string): [string, EventListenerOptions | undefined]; +export declare function parseNVueDataset(attr?: Record): Record; + /** * https://github.com/vuejs/vue-router-next/blob/master/src/query.ts * @internal diff --git a/packages/uni-shared/dist/uni-shared.es.js b/packages/uni-shared/dist/uni-shared.es.js index 7dfbfa5fb2..a448af1169 100644 --- a/packages/uni-shared/dist/uni-shared.es.js +++ b/packages/uni-shared/dist/uni-shared.es.js @@ -681,6 +681,18 @@ function formatH5Log(type, filename, ...args) { console[type].apply(console, [...args, filename]); } +function parseNVueDataset(attr) { + const dataset = {}; + if (attr) { + Object.keys(attr).forEach((key) => { + if (key.indexOf('data-') === 0) { + dataset[key.replace('data-', '')] = attr[key]; + } + }); + } + return dataset; +} + function plusReady(callback) { if (typeof callback !== 'function') { return; @@ -1366,4 +1378,4 @@ function getEnvLocale() { return (lang && lang.replace(/[.:].*/, '')) || 'en'; } -export { ACTION_TYPE_ADD_EVENT, ACTION_TYPE_ADD_WXS_EVENT, ACTION_TYPE_CREATE, ACTION_TYPE_EVENT, ACTION_TYPE_INSERT, ACTION_TYPE_PAGE_CREATE, ACTION_TYPE_PAGE_CREATED, ACTION_TYPE_PAGE_SCROLL, ACTION_TYPE_REMOVE, ACTION_TYPE_REMOVE_ATTRIBUTE, ACTION_TYPE_REMOVE_EVENT, ACTION_TYPE_SET_ATTRIBUTE, ACTION_TYPE_SET_TEXT, ATTR_CHANGE_PREFIX, ATTR_CLASS, ATTR_INNER_HTML, ATTR_STYLE, ATTR_TEXT_CONTENT, ATTR_V_OWNER_ID, ATTR_V_RENDERJS, ATTR_V_SHOW, BACKGROUND_COLOR, BUILT_IN_TAGS, BUILT_IN_TAG_NAMES, COMPONENT_NAME_PREFIX, COMPONENT_PREFIX, COMPONENT_SELECTOR_PREFIX, DATA_RE, E$1 as Emitter, EventChannel, EventModifierFlags, I18N_JSON_DELIMITERS, JSON_PROTOCOL, LINEFEED, MINI_PROGRAM_PAGE_RUNTIME_HOOKS, NAVBAR_HEIGHT, NODE_TYPE_COMMENT, NODE_TYPE_ELEMENT, NODE_TYPE_PAGE, NODE_TYPE_TEXT, NVUE_BUILT_IN_TAGS, NVUE_U_BUILT_IN_TAGS, ON_ADD_TO_FAVORITES, ON_APP_ENTER_BACKGROUND, ON_APP_ENTER_FOREGROUND, ON_BACK_PRESS, ON_ERROR, ON_HIDE, ON_KEYBOARD_HEIGHT_CHANGE, ON_LAUNCH, ON_LOAD, ON_NAVIGATION_BAR_BUTTON_TAP, ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED, ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED, ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED, ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED, ON_PAGE_NOT_FOUND, ON_PAGE_SCROLL, ON_PULL_DOWN_REFRESH, ON_REACH_BOTTOM, ON_REACH_BOTTOM_DISTANCE, ON_READY, ON_RESIZE, ON_SHARE_APP_MESSAGE, ON_SHARE_TIMELINE, ON_SHOW, ON_TAB_ITEM_TAP, ON_THEME_CHANGE, ON_UNHANDLE_REJECTION, ON_UNLOAD, ON_WEB_INVOKE_APP_SERVICE, ON_WXS_INVOKE_CALL_METHOD, PLUS_RE, PRIMARY_COLOR, RENDERJS_MODULES, RESPONSIVE_MIN_WIDTH, SCHEME_RE, SELECTED_COLOR, SLOT_DEFAULT_NAME, TABBAR_HEIGHT, TAGS, UNI_SSR, UNI_SSR_DATA, UNI_SSR_GLOBAL_DATA, UNI_SSR_STORE, UNI_SSR_TITLE, UNI_STORAGE_LOCALE, UniBaseNode, UniCommentNode, UniElement, UniEvent, UniInputElement, UniLifecycleHooks, UniNode, UniTextAreaElement, UniTextNode, WEB_INVOKE_APPSERVICE, WXS_MODULES, WXS_PROTOCOL, addFont, addLeadingSlash, cache, cacheStringFunction, callOptions, createIsCustomElement, createRpx2Unit, createUniEvent, customizeEvent, debounce, decode, decodedQuery, defaultMiniProgramRpx2Unit, defaultNVueRpx2Unit, defaultRpx2Unit, dynamicSlotName, forcePatchProp, formatAppLog, formatDateTime, formatH5Log, formatLog, getCustomDataset, getEnvLocale, getLen, getValueByDataPath, initCustomDatasetOnce, invokeArrayFns, invokeCreateVueAppHook, isAppNVueNativeTag, isAppNativeTag, isBuiltInComponent, isComponentInternalInstance, isComponentTag, isH5CustomElement, isH5NativeTag, isMiniProgramNativeTag, isRootHook, normalizeDataset, normalizeEventType, normalizeTarget, onCreateVueApp, once, parseEventName, parseQuery, parseUrl, passive, plusReady, removeLeadingSlash, resolveComponentInstance, resolveOwnerEl, resolveOwnerVm, sanitise, scrollTo, stringifyQuery, updateElementStyle }; +export { ACTION_TYPE_ADD_EVENT, ACTION_TYPE_ADD_WXS_EVENT, ACTION_TYPE_CREATE, ACTION_TYPE_EVENT, ACTION_TYPE_INSERT, ACTION_TYPE_PAGE_CREATE, ACTION_TYPE_PAGE_CREATED, ACTION_TYPE_PAGE_SCROLL, ACTION_TYPE_REMOVE, ACTION_TYPE_REMOVE_ATTRIBUTE, ACTION_TYPE_REMOVE_EVENT, ACTION_TYPE_SET_ATTRIBUTE, ACTION_TYPE_SET_TEXT, ATTR_CHANGE_PREFIX, ATTR_CLASS, ATTR_INNER_HTML, ATTR_STYLE, ATTR_TEXT_CONTENT, ATTR_V_OWNER_ID, ATTR_V_RENDERJS, ATTR_V_SHOW, BACKGROUND_COLOR, BUILT_IN_TAGS, BUILT_IN_TAG_NAMES, COMPONENT_NAME_PREFIX, COMPONENT_PREFIX, COMPONENT_SELECTOR_PREFIX, DATA_RE, E$1 as Emitter, EventChannel, EventModifierFlags, I18N_JSON_DELIMITERS, JSON_PROTOCOL, LINEFEED, MINI_PROGRAM_PAGE_RUNTIME_HOOKS, NAVBAR_HEIGHT, NODE_TYPE_COMMENT, NODE_TYPE_ELEMENT, NODE_TYPE_PAGE, NODE_TYPE_TEXT, NVUE_BUILT_IN_TAGS, NVUE_U_BUILT_IN_TAGS, ON_ADD_TO_FAVORITES, ON_APP_ENTER_BACKGROUND, ON_APP_ENTER_FOREGROUND, ON_BACK_PRESS, ON_ERROR, ON_HIDE, ON_KEYBOARD_HEIGHT_CHANGE, ON_LAUNCH, ON_LOAD, ON_NAVIGATION_BAR_BUTTON_TAP, ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED, ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED, ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED, ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED, ON_PAGE_NOT_FOUND, ON_PAGE_SCROLL, ON_PULL_DOWN_REFRESH, ON_REACH_BOTTOM, ON_REACH_BOTTOM_DISTANCE, ON_READY, ON_RESIZE, ON_SHARE_APP_MESSAGE, ON_SHARE_TIMELINE, ON_SHOW, ON_TAB_ITEM_TAP, ON_THEME_CHANGE, ON_UNHANDLE_REJECTION, ON_UNLOAD, ON_WEB_INVOKE_APP_SERVICE, ON_WXS_INVOKE_CALL_METHOD, PLUS_RE, PRIMARY_COLOR, RENDERJS_MODULES, RESPONSIVE_MIN_WIDTH, SCHEME_RE, SELECTED_COLOR, SLOT_DEFAULT_NAME, TABBAR_HEIGHT, TAGS, UNI_SSR, UNI_SSR_DATA, UNI_SSR_GLOBAL_DATA, UNI_SSR_STORE, UNI_SSR_TITLE, UNI_STORAGE_LOCALE, UniBaseNode, UniCommentNode, UniElement, UniEvent, UniInputElement, UniLifecycleHooks, UniNode, UniTextAreaElement, UniTextNode, WEB_INVOKE_APPSERVICE, WXS_MODULES, WXS_PROTOCOL, addFont, addLeadingSlash, cache, cacheStringFunction, callOptions, createIsCustomElement, createRpx2Unit, createUniEvent, customizeEvent, debounce, decode, decodedQuery, defaultMiniProgramRpx2Unit, defaultNVueRpx2Unit, defaultRpx2Unit, dynamicSlotName, forcePatchProp, formatAppLog, formatDateTime, formatH5Log, formatLog, getCustomDataset, getEnvLocale, getLen, getValueByDataPath, initCustomDatasetOnce, invokeArrayFns, invokeCreateVueAppHook, isAppNVueNativeTag, isAppNativeTag, isBuiltInComponent, isComponentInternalInstance, isComponentTag, isH5CustomElement, isH5NativeTag, isMiniProgramNativeTag, isRootHook, normalizeDataset, normalizeEventType, normalizeTarget, onCreateVueApp, once, parseEventName, parseNVueDataset, parseQuery, parseUrl, passive, plusReady, removeLeadingSlash, resolveComponentInstance, resolveOwnerEl, resolveOwnerVm, sanitise, scrollTo, stringifyQuery, updateElementStyle }; diff --git a/packages/uni-shared/src/nvue.ts b/packages/uni-shared/src/nvue.ts index a4c66da177..44b5b82a8c 100644 --- a/packages/uni-shared/src/nvue.ts +++ b/packages/uni-shared/src/nvue.ts @@ -1,5 +1,17 @@ import { createApp, ComponentPublicInstance } from 'vue' +export function parseNVueDataset(attr?: Record) { + const dataset: Record = {} + if (attr) { + Object.keys(attr).forEach((key) => { + if (key.indexOf('data-') === 0) { + dataset[key.replace('data-', '')] = attr[key] + } + }) + } + return dataset +} + export interface Vue { createApp: typeof createApp } @@ -85,6 +97,7 @@ export interface NVueElement { ref: string text?: string + attr: Record styleSheet: Record>> classList: string[] parentNode: NVueElement | null -- GitLab