uni-shared.es.js 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591
  1. import { isHTMLTag, isSVGTag, hyphenate, camelize, normalizeStyle as normalizeStyle$1, isArray, isString, parseStringStyle, normalizeClass as normalizeClass$1, isFunction, isPlainObject, extend, capitalize } from '@vue/shared';
  2. const BUILT_IN_TAG_NAMES = [
  3. 'ad',
  4. 'ad-content-page',
  5. 'ad-draw',
  6. 'audio',
  7. 'button',
  8. 'camera',
  9. 'canvas',
  10. 'checkbox',
  11. 'checkbox-group',
  12. 'cover-image',
  13. 'cover-view',
  14. 'editor',
  15. 'form',
  16. 'functional-page-navigator',
  17. 'icon',
  18. 'image',
  19. 'input',
  20. 'label',
  21. 'live-player',
  22. 'live-pusher',
  23. 'map',
  24. 'movable-area',
  25. 'movable-view',
  26. 'navigator',
  27. 'official-account',
  28. 'open-data',
  29. 'picker',
  30. 'picker-view',
  31. 'picker-view-column',
  32. 'progress',
  33. 'radio',
  34. 'radio-group',
  35. 'rich-text',
  36. 'scroll-view',
  37. 'slider',
  38. 'swiper',
  39. 'swiper-item',
  40. 'switch',
  41. 'text',
  42. 'textarea',
  43. 'video',
  44. 'view',
  45. 'web-view',
  46. ];
  47. const BUILT_IN_TAGS = BUILT_IN_TAG_NAMES.map((tag) => 'uni-' + tag);
  48. const TAGS = [
  49. 'app',
  50. 'layout',
  51. 'content',
  52. 'main',
  53. 'top-window',
  54. 'left-window',
  55. 'right-window',
  56. 'tabbar',
  57. 'page',
  58. 'page-head',
  59. 'page-wrapper',
  60. 'page-body',
  61. 'page-refresh',
  62. 'actionsheet',
  63. 'modal',
  64. 'toast',
  65. 'resize-sensor',
  66. 'shadow-root',
  67. ].map((tag) => 'uni-' + tag);
  68. const NVUE_BUILT_IN_TAGS = [
  69. 'svg',
  70. 'view',
  71. 'a',
  72. 'div',
  73. 'img',
  74. 'image',
  75. 'text',
  76. 'span',
  77. 'input',
  78. 'textarea',
  79. 'spinner',
  80. 'select',
  81. // slider 被自定义 u-slider 替代
  82. // 'slider',
  83. 'slider-neighbor',
  84. 'indicator',
  85. 'canvas',
  86. 'list',
  87. 'cell',
  88. 'header',
  89. 'loading',
  90. 'loading-indicator',
  91. 'refresh',
  92. 'scrollable',
  93. 'scroller',
  94. 'video',
  95. 'web',
  96. 'embed',
  97. 'tabbar',
  98. 'tabheader',
  99. 'datepicker',
  100. 'timepicker',
  101. 'marquee',
  102. 'countdown',
  103. 'dc-switch',
  104. 'waterfall',
  105. 'richtext',
  106. 'recycle-list',
  107. 'u-scalable',
  108. 'barcode',
  109. 'gcanvas',
  110. ];
  111. const UVUE_BUILT_IN_TAGS = [
  112. 'loading-indicator',
  113. 'list-view',
  114. 'list-item',
  115. 'swiper',
  116. 'swiper-item',
  117. 'rich-text',
  118. 'sticky-view',
  119. 'sticky-header',
  120. 'sticky-section',
  121. // 自定义
  122. 'uni-slider',
  123. // 原生实现
  124. 'button',
  125. ];
  126. const UVUE_WEB_BUILT_IN_TAGS = [
  127. 'list-view',
  128. 'list-item',
  129. 'sticky-section',
  130. 'sticky-header',
  131. 'cloud-db-element',
  132. ].map((tag) => 'uni-' + tag);
  133. const UVUE_IOS_BUILT_IN_TAGS = [
  134. 'scroll-view',
  135. 'web-view',
  136. 'slider',
  137. 'swiper',
  138. 'swiper-item',
  139. 'rich-text',
  140. 'button',
  141. 'list-view',
  142. 'list-item',
  143. 'switch',
  144. 'sticky-header',
  145. 'sticky-section',
  146. ];
  147. const NVUE_U_BUILT_IN_TAGS = [
  148. 'u-text',
  149. 'u-image',
  150. 'u-input',
  151. 'u-textarea',
  152. 'u-video',
  153. 'u-web-view',
  154. 'u-slider',
  155. 'u-ad',
  156. 'u-ad-draw',
  157. 'u-rich-text',
  158. ];
  159. const UNI_UI_CONFLICT_TAGS = ['list-item'].map((tag) => 'uni-' + tag);
  160. function isBuiltInComponent(tag) {
  161. if (UNI_UI_CONFLICT_TAGS.indexOf(tag) !== -1) {
  162. return false;
  163. }
  164. // h5 平台会被转换为 v-uni-
  165. const realTag = 'uni-' + tag.replace('v-uni-', '');
  166. // TODO 区分x和非x
  167. return (BUILT_IN_TAGS.indexOf(realTag) !== -1 ||
  168. UVUE_WEB_BUILT_IN_TAGS.indexOf(realTag) !== -1);
  169. }
  170. function isH5CustomElement(tag, isX = false) {
  171. if (isX && UVUE_WEB_BUILT_IN_TAGS.indexOf(tag) !== -1) {
  172. return true;
  173. }
  174. return TAGS.indexOf(tag) !== -1 || BUILT_IN_TAGS.indexOf(tag) !== -1;
  175. }
  176. function isUniXElement(name) {
  177. return /^I?Uni.*Element(?:Impl)?$/.test(name);
  178. }
  179. function isH5NativeTag(tag) {
  180. return (tag !== 'head' &&
  181. (isHTMLTag(tag) || isSVGTag(tag)) &&
  182. !isBuiltInComponent(tag));
  183. }
  184. function isAppNativeTag(tag) {
  185. return isHTMLTag(tag) || isSVGTag(tag) || isBuiltInComponent(tag);
  186. }
  187. const NVUE_CUSTOM_COMPONENTS = [
  188. 'ad',
  189. 'ad-draw',
  190. 'button',
  191. 'checkbox-group',
  192. 'checkbox',
  193. 'form',
  194. 'icon',
  195. 'label',
  196. 'movable-area',
  197. 'movable-view',
  198. 'navigator',
  199. 'picker',
  200. 'progress',
  201. 'radio-group',
  202. 'radio',
  203. 'rich-text',
  204. 'swiper-item',
  205. 'swiper',
  206. 'switch',
  207. 'slider',
  208. 'picker-view',
  209. 'picker-view-column',
  210. ];
  211. function isAppUVueNativeTag(tag) {
  212. // 前端实现的内置组件都会注册一个根组件
  213. if (tag.startsWith('uni-') && tag.endsWith('-element')) {
  214. return true;
  215. }
  216. if (UVUE_BUILT_IN_TAGS.includes(tag)) {
  217. return true;
  218. }
  219. if (NVUE_CUSTOM_COMPONENTS.includes(tag)) {
  220. return false;
  221. }
  222. if (isBuiltInComponent(tag)) {
  223. return true;
  224. }
  225. // u-text,u-video...
  226. if (NVUE_U_BUILT_IN_TAGS.includes(tag)) {
  227. return true;
  228. }
  229. return false;
  230. }
  231. function isAppNVueNativeTag(tag) {
  232. if (NVUE_BUILT_IN_TAGS.includes(tag)) {
  233. return true;
  234. }
  235. if (NVUE_CUSTOM_COMPONENTS.includes(tag)) {
  236. return false;
  237. }
  238. if (isBuiltInComponent(tag)) {
  239. return true;
  240. }
  241. // u-text,u-video...
  242. if (NVUE_U_BUILT_IN_TAGS.includes(tag)) {
  243. return true;
  244. }
  245. return false;
  246. }
  247. function isMiniProgramNativeTag(tag) {
  248. return isBuiltInComponent(tag);
  249. }
  250. function createIsCustomElement(tags = []) {
  251. return function isCustomElement(tag) {
  252. return tags.includes(tag);
  253. };
  254. }
  255. function isComponentTag(tag) {
  256. return tag[0].toLowerCase() + tag.slice(1) === 'component';
  257. }
  258. const COMPONENT_SELECTOR_PREFIX = 'uni-';
  259. const COMPONENT_PREFIX = 'v-' + COMPONENT_SELECTOR_PREFIX;
  260. const LINEFEED = '\n';
  261. const NAVBAR_HEIGHT = 44;
  262. const TABBAR_HEIGHT = 50;
  263. const ON_REACH_BOTTOM_DISTANCE = 50;
  264. const RESPONSIVE_MIN_WIDTH = 768;
  265. const UNI_STORAGE_LOCALE = 'UNI_LOCALE';
  266. // quickapp-webview 不能使用 default 作为插槽名称
  267. const SLOT_DEFAULT_NAME = 'd';
  268. const COMPONENT_NAME_PREFIX = 'VUni';
  269. const I18N_JSON_DELIMITERS = ['%', '%'];
  270. const PRIMARY_COLOR = '#007aff';
  271. const SELECTED_COLOR = '#0062cc'; // 选中的颜色,如选项卡默认的选中颜色
  272. const BACKGROUND_COLOR = '#f7f7f7'; // 背景色,如标题栏默认背景色
  273. const UNI_SSR = '__uniSSR';
  274. const UNI_SSR_TITLE = 'title';
  275. const UNI_SSR_STORE = 'store';
  276. const UNI_SSR_DATA = 'data';
  277. const UNI_SSR_GLOBAL_DATA = 'globalData';
  278. const SCHEME_RE = /^([a-z-]+:)?\/\//i;
  279. const DATA_RE = /^data:.*,.*/;
  280. const WEB_INVOKE_APPSERVICE = 'WEB_INVOKE_APPSERVICE';
  281. const WXS_PROTOCOL = 'wxs://';
  282. const JSON_PROTOCOL = 'json://';
  283. const WXS_MODULES = 'wxsModules';
  284. const RENDERJS_MODULES = 'renderjsModules';
  285. // lifecycle
  286. // App and Page
  287. const ON_SHOW = 'onShow';
  288. const ON_HIDE = 'onHide';
  289. //App
  290. const ON_LAUNCH = 'onLaunch';
  291. const ON_ERROR = 'onError';
  292. const ON_THEME_CHANGE = 'onThemeChange';
  293. const OFF_THEME_CHANGE = 'offThemeChange';
  294. const ON_KEYBOARD_HEIGHT_CHANGE = 'onKeyboardHeightChange';
  295. const ON_PAGE_NOT_FOUND = 'onPageNotFound';
  296. const ON_UNHANDLE_REJECTION = 'onUnhandledRejection';
  297. const ON_EXIT = 'onExit';
  298. //Page
  299. const ON_LOAD = 'onLoad';
  300. const ON_READY = 'onReady';
  301. const ON_UNLOAD = 'onUnload';
  302. // 百度特有
  303. const ON_INIT = 'onInit';
  304. // 微信特有
  305. const ON_SAVE_EXIT_STATE = 'onSaveExitState';
  306. const ON_RESIZE = 'onResize';
  307. const ON_BACK_PRESS = 'onBackPress';
  308. const ON_PAGE_SCROLL = 'onPageScroll';
  309. const ON_TAB_ITEM_TAP = 'onTabItemTap';
  310. const ON_REACH_BOTTOM = 'onReachBottom';
  311. const ON_PULL_DOWN_REFRESH = 'onPullDownRefresh';
  312. const ON_SHARE_TIMELINE = 'onShareTimeline';
  313. const ON_ADD_TO_FAVORITES = 'onAddToFavorites';
  314. const ON_SHARE_APP_MESSAGE = 'onShareAppMessage';
  315. // navigationBar
  316. const ON_NAVIGATION_BAR_BUTTON_TAP = 'onNavigationBarButtonTap';
  317. const ON_NAVIGATION_BAR_CHANGE = 'onNavigationBarChange';
  318. const ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED = 'onNavigationBarSearchInputClicked';
  319. const ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED = 'onNavigationBarSearchInputChanged';
  320. const ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED = 'onNavigationBarSearchInputConfirmed';
  321. const ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED = 'onNavigationBarSearchInputFocusChanged';
  322. // framework
  323. const ON_APP_ENTER_FOREGROUND = 'onAppEnterForeground';
  324. const ON_APP_ENTER_BACKGROUND = 'onAppEnterBackground';
  325. const ON_WEB_INVOKE_APP_SERVICE = 'onWebInvokeAppService';
  326. const ON_WXS_INVOKE_CALL_METHOD = 'onWxsInvokeCallMethod';
  327. function isComponentInternalInstance(vm) {
  328. return !!vm.appContext;
  329. }
  330. function resolveComponentInstance(instance) {
  331. return (instance &&
  332. (isComponentInternalInstance(instance) ? instance.proxy : instance));
  333. }
  334. function resolveOwnerVm(vm) {
  335. if (!vm) {
  336. return;
  337. }
  338. let componentName = vm.type.name;
  339. while (componentName && isBuiltInComponent(hyphenate(componentName))) {
  340. // ownerInstance 内置组件需要使用父 vm
  341. vm = vm.parent;
  342. componentName = vm.type.name;
  343. }
  344. return vm.proxy;
  345. }
  346. function isElement(el) {
  347. // Element
  348. return el.nodeType === 1;
  349. }
  350. function resolveOwnerEl(instance, multi = false) {
  351. const { vnode } = instance;
  352. if (isElement(vnode.el)) {
  353. return multi ? (vnode.el ? [vnode.el] : []) : vnode.el;
  354. }
  355. const { subTree } = instance;
  356. // ShapeFlags.ARRAY_CHILDREN = 1<<4
  357. if (subTree.shapeFlag & 16) {
  358. const elemVNodes = subTree.children.filter((vnode) => vnode.el && isElement(vnode.el));
  359. if (elemVNodes.length > 0) {
  360. if (multi) {
  361. return elemVNodes.map((node) => node.el);
  362. }
  363. return elemVNodes[0].el;
  364. }
  365. }
  366. return multi ? (vnode.el ? [vnode.el] : []) : vnode.el;
  367. }
  368. function dynamicSlotName(name) {
  369. return name === 'default' ? SLOT_DEFAULT_NAME : name;
  370. }
  371. const customizeRE = /:/g;
  372. function customizeEvent(str) {
  373. return camelize(str.replace(customizeRE, '-'));
  374. }
  375. function normalizeStyle(value) {
  376. if (value instanceof Map) {
  377. const styleObject = {};
  378. value.forEach((value, key) => {
  379. styleObject[key] = value;
  380. });
  381. return normalizeStyle$1(styleObject);
  382. }
  383. else if (isArray(value)) {
  384. const res = {};
  385. for (let i = 0; i < value.length; i++) {
  386. const item = value[i];
  387. const normalized = isString(item)
  388. ? parseStringStyle(item)
  389. : normalizeStyle(item);
  390. if (normalized) {
  391. for (const key in normalized) {
  392. res[key] = normalized[key];
  393. }
  394. }
  395. }
  396. return res;
  397. }
  398. else {
  399. return normalizeStyle$1(value);
  400. }
  401. }
  402. function normalizeClass(value) {
  403. let res = '';
  404. if (value instanceof Map) {
  405. value.forEach((value, key) => {
  406. if (value) {
  407. res += key + ' ';
  408. }
  409. });
  410. }
  411. else if (isArray(value)) {
  412. for (let i = 0; i < value.length; i++) {
  413. const normalized = normalizeClass(value[i]);
  414. if (normalized) {
  415. res += normalized + ' ';
  416. }
  417. }
  418. }
  419. else {
  420. res = normalizeClass$1(value);
  421. }
  422. return res.trim();
  423. }
  424. function normalizeProps(props) {
  425. if (!props)
  426. return null;
  427. let { class: klass, style } = props;
  428. if (klass && !isString(klass)) {
  429. props.class = normalizeClass(klass);
  430. }
  431. if (style) {
  432. props.style = normalizeStyle(style);
  433. }
  434. return props;
  435. }
  436. let lastLogTime = 0;
  437. function formatLog(module, ...args) {
  438. const now = Date.now();
  439. const diff = lastLogTime ? now - lastLogTime : 0;
  440. lastLogTime = now;
  441. return `[${now}][${diff}ms][${module}]:${args
  442. .map((arg) => JSON.stringify(arg))
  443. .join(' ')}`;
  444. }
  445. function cache(fn) {
  446. const cache = Object.create(null);
  447. return (str) => {
  448. const hit = cache[str];
  449. return hit || (cache[str] = fn(str));
  450. };
  451. }
  452. function cacheStringFunction(fn) {
  453. return cache(fn);
  454. }
  455. function getLen(str = '') {
  456. return ('' + str).replace(/[^\x00-\xff]/g, '**').length;
  457. }
  458. function hasLeadingSlash(str) {
  459. return str.indexOf('/') === 0;
  460. }
  461. function addLeadingSlash(str) {
  462. return hasLeadingSlash(str) ? str : '/' + str;
  463. }
  464. function removeLeadingSlash(str) {
  465. return hasLeadingSlash(str) ? str.slice(1) : str;
  466. }
  467. const invokeArrayFns = (fns, arg) => {
  468. let ret;
  469. for (let i = 0; i < fns.length; i++) {
  470. ret = fns[i](arg);
  471. }
  472. return ret;
  473. };
  474. function updateElementStyle(element, styles) {
  475. for (const attrName in styles) {
  476. element.style[attrName] = styles[attrName];
  477. }
  478. }
  479. function once(fn, ctx = null) {
  480. let res;
  481. return ((...args) => {
  482. if (fn) {
  483. res = fn.apply(ctx, args);
  484. fn = null;
  485. }
  486. return res;
  487. });
  488. }
  489. const sanitise = (val) => (val && JSON.parse(JSON.stringify(val))) || val;
  490. const _completeValue = (value) => (value > 9 ? value : '0' + value);
  491. function formatDateTime({ date = new Date(), mode = 'date' }) {
  492. if (mode === 'time') {
  493. return (_completeValue(date.getHours()) + ':' + _completeValue(date.getMinutes()));
  494. }
  495. else {
  496. return (date.getFullYear() +
  497. '-' +
  498. _completeValue(date.getMonth() + 1) +
  499. '-' +
  500. _completeValue(date.getDate()));
  501. }
  502. }
  503. function callOptions(options, data) {
  504. options = options || {};
  505. if (isString(data)) {
  506. data = {
  507. errMsg: data,
  508. };
  509. }
  510. if (/:ok$/.test(data.errMsg)) {
  511. if (isFunction(options.success)) {
  512. options.success(data);
  513. }
  514. }
  515. else {
  516. if (isFunction(options.fail)) {
  517. options.fail(data);
  518. }
  519. }
  520. if (isFunction(options.complete)) {
  521. options.complete(data);
  522. }
  523. }
  524. function getValueByDataPath(obj, path) {
  525. if (!isString(path)) {
  526. return;
  527. }
  528. path = path.replace(/\[(\d+)\]/g, '.$1');
  529. const parts = path.split('.');
  530. let key = parts[0];
  531. if (!obj) {
  532. obj = {};
  533. }
  534. if (parts.length === 1) {
  535. return obj[key];
  536. }
  537. return getValueByDataPath(obj[key], parts.slice(1).join('.'));
  538. }
  539. function sortObject(obj) {
  540. let sortObj = {};
  541. if (isPlainObject(obj)) {
  542. Object.keys(obj)
  543. .sort()
  544. .forEach((key) => {
  545. const _key = key;
  546. sortObj[_key] = obj[_key];
  547. });
  548. }
  549. return !Object.keys(sortObj) ? obj : sortObj;
  550. }
  551. function formatKey(key) {
  552. return camelize(key.substring(5));
  553. }
  554. // question/139181,增加副作用,避免 initCustomDataset 在 build 下被 tree-shaking
  555. const initCustomDatasetOnce = /*#__PURE__*/ once(() => {
  556. const prototype = HTMLElement.prototype;
  557. const setAttribute = prototype.setAttribute;
  558. prototype.setAttribute = function (key, value) {
  559. if (key.startsWith('data-') && this.tagName.startsWith('UNI-')) {
  560. const dataset = this.__uniDataset ||
  561. (this.__uniDataset = {});
  562. dataset[formatKey(key)] = value;
  563. }
  564. setAttribute.call(this, key, value);
  565. };
  566. const removeAttribute = prototype.removeAttribute;
  567. prototype.removeAttribute = function (key) {
  568. if (this.__uniDataset &&
  569. key.startsWith('data-') &&
  570. this.tagName.startsWith('UNI-')) {
  571. delete this.__uniDataset[formatKey(key)];
  572. }
  573. removeAttribute.call(this, key);
  574. };
  575. });
  576. function getCustomDataset(el) {
  577. return extend({}, el.dataset, el.__uniDataset);
  578. }
  579. const unitRE = new RegExp(`"[^"]+"|'[^']+'|url\\([^)]+\\)|(\\d*\\.?\\d+)[r|u]px`, 'g');
  580. function toFixed(number, precision) {
  581. const multiplier = Math.pow(10, precision + 1);
  582. const wholeNumber = Math.floor(number * multiplier);
  583. return (Math.round(wholeNumber / 10) * 10) / multiplier;
  584. }
  585. const defaultRpx2Unit = {
  586. unit: 'rem',
  587. unitRatio: 10 / 320,
  588. unitPrecision: 5,
  589. };
  590. const defaultMiniProgramRpx2Unit = {
  591. unit: 'rpx',
  592. unitRatio: 1,
  593. unitPrecision: 1,
  594. };
  595. const defaultNVueRpx2Unit = defaultMiniProgramRpx2Unit;
  596. function createRpx2Unit(unit, unitRatio, unitPrecision) {
  597. // ignore: rpxCalcIncludeWidth
  598. return (val) => val.replace(unitRE, (m, $1) => {
  599. if (!$1) {
  600. return m;
  601. }
  602. if (unitRatio === 1) {
  603. return `${$1}${unit}`;
  604. }
  605. const value = toFixed(parseFloat($1) * unitRatio, unitPrecision);
  606. return value === 0 ? '0' : `${value}${unit}`;
  607. });
  608. }
  609. function passive(passive) {
  610. return { passive };
  611. }
  612. function normalizeDataset(el) {
  613. // TODO
  614. return JSON.parse(JSON.stringify(el.dataset || {}));
  615. }
  616. function normalizeTarget(el) {
  617. const { id, offsetTop, offsetLeft } = el;
  618. return {
  619. id,
  620. dataset: getCustomDataset(el),
  621. offsetTop,
  622. offsetLeft,
  623. };
  624. }
  625. function addFont(family, source, desc) {
  626. const fonts = document.fonts;
  627. if (fonts) {
  628. const fontFace = new FontFace(family, source, desc);
  629. return fontFace.load().then(() => {
  630. fonts.add && fonts.add(fontFace);
  631. });
  632. }
  633. return new Promise((resolve) => {
  634. const style = document.createElement('style');
  635. const values = [];
  636. if (desc) {
  637. const { style, weight, stretch, unicodeRange, variant, featureSettings } = desc;
  638. style && values.push(`font-style:${style}`);
  639. weight && values.push(`font-weight:${weight}`);
  640. stretch && values.push(`font-stretch:${stretch}`);
  641. unicodeRange && values.push(`unicode-range:${unicodeRange}`);
  642. variant && values.push(`font-variant:${variant}`);
  643. featureSettings && values.push(`font-feature-settings:${featureSettings}`);
  644. }
  645. style.innerText = `@font-face{font-family:"${family}";src:${source};${values.join(';')}}`;
  646. document.head.appendChild(style);
  647. resolve();
  648. });
  649. }
  650. function scrollTo(scrollTop, duration, isH5) {
  651. if (isString(scrollTop)) {
  652. const el = document.querySelector(scrollTop);
  653. if (el) {
  654. const { top } = el.getBoundingClientRect();
  655. scrollTop = top + window.pageYOffset;
  656. // 如果存在,减去 <uni-page-head> 高度
  657. const pageHeader = document.querySelector('uni-page-head');
  658. if (pageHeader) {
  659. scrollTop -= pageHeader.offsetHeight;
  660. }
  661. }
  662. }
  663. if (scrollTop < 0) {
  664. scrollTop = 0;
  665. }
  666. const documentElement = document.documentElement;
  667. const { clientHeight, scrollHeight } = documentElement;
  668. scrollTop = Math.min(scrollTop, scrollHeight - clientHeight);
  669. if (duration === 0) {
  670. // 部分浏览器(比如微信)中 scrollTop 的值需要通过 document.body 来控制
  671. documentElement.scrollTop = document.body.scrollTop = scrollTop;
  672. return;
  673. }
  674. if (window.scrollY === scrollTop) {
  675. return;
  676. }
  677. const scrollTo = (duration) => {
  678. if (duration <= 0) {
  679. window.scrollTo(0, scrollTop);
  680. return;
  681. }
  682. const distaince = scrollTop - window.scrollY;
  683. requestAnimationFrame(function () {
  684. window.scrollTo(0, window.scrollY + (distaince / duration) * 10);
  685. scrollTo(duration - 10);
  686. });
  687. };
  688. scrollTo(duration);
  689. }
  690. const encode = encodeURIComponent;
  691. function stringifyQuery(obj, encodeStr = encode) {
  692. const res = obj
  693. ? Object.keys(obj)
  694. .map((key) => {
  695. let val = obj[key];
  696. if (typeof val === undefined || val === null) {
  697. val = '';
  698. }
  699. else if (isPlainObject(val)) {
  700. val = JSON.stringify(val);
  701. }
  702. return encodeStr(key) + '=' + encodeStr(val);
  703. })
  704. .filter((x) => x.length > 0)
  705. .join('&')
  706. : null;
  707. return res ? `?${res}` : '';
  708. }
  709. /**
  710. * Decode text using `decodeURIComponent`. Returns the original text if it
  711. * fails.
  712. *
  713. * @param text - string to decode
  714. * @returns decoded string
  715. */
  716. function decode(text) {
  717. try {
  718. return decodeURIComponent('' + text);
  719. }
  720. catch (err) { }
  721. return '' + text;
  722. }
  723. function decodedQuery(query = {}) {
  724. const decodedQuery = {};
  725. Object.keys(query).forEach((name) => {
  726. try {
  727. decodedQuery[name] = decode(query[name]);
  728. }
  729. catch (e) {
  730. decodedQuery[name] = query[name];
  731. }
  732. });
  733. return decodedQuery;
  734. }
  735. const PLUS_RE = /\+/g; // %2B
  736. /**
  737. * https://github.com/vuejs/vue-router-next/blob/master/src/query.ts
  738. * @internal
  739. *
  740. * @param search - search string to parse
  741. * @returns a query object
  742. */
  743. function parseQuery(search) {
  744. const query = {};
  745. // avoid creating an object with an empty key and empty value
  746. // because of split('&')
  747. if (search === '' || search === '?')
  748. return query;
  749. const hasLeadingIM = search[0] === '?';
  750. const searchParams = (hasLeadingIM ? search.slice(1) : search).split('&');
  751. for (let i = 0; i < searchParams.length; ++i) {
  752. // pre decode the + into space
  753. const searchParam = searchParams[i].replace(PLUS_RE, ' ');
  754. // allow the = character
  755. let eqPos = searchParam.indexOf('=');
  756. let key = decode(eqPos < 0 ? searchParam : searchParam.slice(0, eqPos));
  757. let value = eqPos < 0 ? null : decode(searchParam.slice(eqPos + 1));
  758. if (key in query) {
  759. // an extra variable for ts types
  760. let currentValue = query[key];
  761. if (!isArray(currentValue)) {
  762. currentValue = query[key] = [currentValue];
  763. }
  764. currentValue.push(value);
  765. }
  766. else {
  767. query[key] = value;
  768. }
  769. }
  770. return query;
  771. }
  772. function parseUrl(url) {
  773. const [path, querystring] = url.split('?', 2);
  774. return {
  775. path,
  776. query: parseQuery(querystring || ''),
  777. };
  778. }
  779. function parseNVueDataset(attr) {
  780. const dataset = {};
  781. if (attr) {
  782. Object.keys(attr).forEach((key) => {
  783. if (key.indexOf('data-') === 0) {
  784. dataset[key.replace('data-', '')] = attr[key];
  785. }
  786. });
  787. }
  788. return dataset;
  789. }
  790. function plusReady(callback) {
  791. if (!isFunction(callback)) {
  792. return;
  793. }
  794. if (window.plus) {
  795. return callback();
  796. }
  797. document.addEventListener('plusready', callback);
  798. }
  799. class DOMException extends Error {
  800. constructor(message) {
  801. super(message);
  802. this.name = 'DOMException';
  803. }
  804. }
  805. function normalizeEventType(type, options) {
  806. if (options) {
  807. if (options.capture) {
  808. type += 'Capture';
  809. }
  810. if (options.once) {
  811. type += 'Once';
  812. }
  813. if (options.passive) {
  814. type += 'Passive';
  815. }
  816. }
  817. return `on${capitalize(camelize(type))}`;
  818. }
  819. class UniEvent {
  820. constructor(type, opts) {
  821. this.defaultPrevented = false;
  822. this.timeStamp = Date.now();
  823. this._stop = false;
  824. this._end = false;
  825. this.type = type;
  826. this.bubbles = !!opts.bubbles;
  827. this.cancelable = !!opts.cancelable;
  828. }
  829. preventDefault() {
  830. this.defaultPrevented = true;
  831. }
  832. stopImmediatePropagation() {
  833. this._end = this._stop = true;
  834. }
  835. stopPropagation() {
  836. this._stop = true;
  837. }
  838. }
  839. function createUniEvent(evt) {
  840. if (evt instanceof UniEvent) {
  841. return evt;
  842. }
  843. const [type] = parseEventName(evt.type);
  844. const uniEvent = new UniEvent(type, {
  845. bubbles: false,
  846. cancelable: false,
  847. });
  848. extend(uniEvent, evt);
  849. return uniEvent;
  850. }
  851. class UniEventTarget {
  852. constructor() {
  853. this.listeners = Object.create(null);
  854. }
  855. dispatchEvent(evt) {
  856. const listeners = this.listeners[evt.type];
  857. if (!listeners) {
  858. if ((process.env.NODE_ENV !== 'production')) {
  859. console.error(formatLog('dispatchEvent', this.nodeId), evt.type, 'not found');
  860. }
  861. return false;
  862. }
  863. // 格式化事件类型
  864. const event = createUniEvent(evt);
  865. const len = listeners.length;
  866. for (let i = 0; i < len; i++) {
  867. listeners[i].call(this, event);
  868. if (event._end) {
  869. break;
  870. }
  871. }
  872. return event.cancelable && event.defaultPrevented;
  873. }
  874. addEventListener(type, listener, options) {
  875. type = normalizeEventType(type, options);
  876. (this.listeners[type] || (this.listeners[type] = [])).push(listener);
  877. }
  878. removeEventListener(type, callback, options) {
  879. type = normalizeEventType(type, options);
  880. const listeners = this.listeners[type];
  881. if (!listeners) {
  882. return;
  883. }
  884. const index = listeners.indexOf(callback);
  885. if (index > -1) {
  886. listeners.splice(index, 1);
  887. }
  888. }
  889. }
  890. const optionsModifierRE = /(?:Once|Passive|Capture)$/;
  891. function parseEventName(name) {
  892. let options;
  893. if (optionsModifierRE.test(name)) {
  894. options = {};
  895. let m;
  896. while ((m = name.match(optionsModifierRE))) {
  897. name = name.slice(0, name.length - m[0].length);
  898. options[m[0].toLowerCase()] = true;
  899. }
  900. }
  901. return [hyphenate(name.slice(2)), options];
  902. }
  903. const EventModifierFlags = /*#__PURE__*/ (() => {
  904. return {
  905. stop: 1,
  906. prevent: 1 << 1,
  907. self: 1 << 2,
  908. };
  909. })();
  910. function encodeModifier(modifiers) {
  911. let flag = 0;
  912. if (modifiers.includes('stop')) {
  913. flag |= EventModifierFlags.stop;
  914. }
  915. if (modifiers.includes('prevent')) {
  916. flag |= EventModifierFlags.prevent;
  917. }
  918. if (modifiers.includes('self')) {
  919. flag |= EventModifierFlags.self;
  920. }
  921. return flag;
  922. }
  923. const NODE_TYPE_PAGE = 0;
  924. const NODE_TYPE_ELEMENT = 1;
  925. const NODE_TYPE_TEXT = 3;
  926. const NODE_TYPE_COMMENT = 8;
  927. function sibling(node, type) {
  928. const { parentNode } = node;
  929. if (!parentNode) {
  930. return null;
  931. }
  932. const { childNodes } = parentNode;
  933. return childNodes[childNodes.indexOf(node) + (type === 'n' ? 1 : -1)] || null;
  934. }
  935. function removeNode(node) {
  936. const { parentNode } = node;
  937. if (parentNode) {
  938. const { childNodes } = parentNode;
  939. const index = childNodes.indexOf(node);
  940. if (index > -1) {
  941. node.parentNode = null;
  942. childNodes.splice(index, 1);
  943. }
  944. }
  945. }
  946. function checkNodeId(node) {
  947. if (!node.nodeId && node.pageNode) {
  948. node.nodeId = node.pageNode.genId();
  949. }
  950. }
  951. // 为优化性能,各平台不使用proxy来实现node的操作拦截,而是直接通过pageNode定制
  952. class UniNode extends UniEventTarget {
  953. constructor(nodeType, nodeName, container) {
  954. super();
  955. this.pageNode = null;
  956. this.parentNode = null;
  957. this._text = null;
  958. if (container) {
  959. const { pageNode } = container;
  960. if (pageNode) {
  961. this.pageNode = pageNode;
  962. this.nodeId = pageNode.genId();
  963. !pageNode.isUnmounted && pageNode.onCreate(this, nodeName);
  964. }
  965. }
  966. this.nodeType = nodeType;
  967. this.nodeName = nodeName;
  968. this.childNodes = [];
  969. }
  970. get firstChild() {
  971. return this.childNodes[0] || null;
  972. }
  973. get lastChild() {
  974. const { childNodes } = this;
  975. const length = childNodes.length;
  976. return length ? childNodes[length - 1] : null;
  977. }
  978. get nextSibling() {
  979. return sibling(this, 'n');
  980. }
  981. get nodeValue() {
  982. return null;
  983. }
  984. set nodeValue(_val) { }
  985. get textContent() {
  986. return this._text || '';
  987. }
  988. set textContent(text) {
  989. this._text = text;
  990. if (this.pageNode && !this.pageNode.isUnmounted) {
  991. this.pageNode.onTextContent(this, text);
  992. }
  993. }
  994. get parentElement() {
  995. const { parentNode } = this;
  996. if (parentNode && parentNode.nodeType === NODE_TYPE_ELEMENT) {
  997. return parentNode;
  998. }
  999. return null;
  1000. }
  1001. get previousSibling() {
  1002. return sibling(this, 'p');
  1003. }
  1004. appendChild(newChild) {
  1005. return this.insertBefore(newChild, null);
  1006. }
  1007. cloneNode(deep) {
  1008. const cloned = extend(Object.create(Object.getPrototypeOf(this)), this);
  1009. const { attributes } = cloned;
  1010. if (attributes) {
  1011. cloned.attributes = extend({}, attributes);
  1012. }
  1013. if (deep) {
  1014. cloned.childNodes = cloned.childNodes.map((childNode) => childNode.cloneNode(true));
  1015. }
  1016. return cloned;
  1017. }
  1018. insertBefore(newChild, refChild) {
  1019. // 先从现在的父节点移除(注意:不能触发onRemoveChild,否则会生成先remove该 id,再 insert)
  1020. removeNode(newChild);
  1021. newChild.pageNode = this.pageNode;
  1022. newChild.parentNode = this;
  1023. checkNodeId(newChild);
  1024. const { childNodes } = this;
  1025. if (refChild) {
  1026. const index = childNodes.indexOf(refChild);
  1027. if (index === -1) {
  1028. throw new DOMException(`Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.`);
  1029. }
  1030. childNodes.splice(index, 0, newChild);
  1031. }
  1032. else {
  1033. childNodes.push(newChild);
  1034. }
  1035. return this.pageNode && !this.pageNode.isUnmounted
  1036. ? this.pageNode.onInsertBefore(this, newChild, refChild)
  1037. : newChild;
  1038. }
  1039. removeChild(oldChild) {
  1040. const { childNodes } = this;
  1041. const index = childNodes.indexOf(oldChild);
  1042. if (index === -1) {
  1043. throw new DOMException(`Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.`);
  1044. }
  1045. oldChild.parentNode = null;
  1046. childNodes.splice(index, 1);
  1047. return this.pageNode && !this.pageNode.isUnmounted
  1048. ? this.pageNode.onRemoveChild(oldChild)
  1049. : oldChild;
  1050. }
  1051. }
  1052. const ATTR_CLASS = 'class';
  1053. const ATTR_STYLE = 'style';
  1054. const ATTR_INNER_HTML = 'innerHTML';
  1055. const ATTR_TEXT_CONTENT = 'textContent';
  1056. const ATTR_V_SHOW = '.vShow';
  1057. const ATTR_V_OWNER_ID = '.vOwnerId';
  1058. const ATTR_V_RENDERJS = '.vRenderjs';
  1059. const ATTR_CHANGE_PREFIX = 'change:';
  1060. class UniBaseNode extends UniNode {
  1061. constructor(nodeType, nodeName, container) {
  1062. super(nodeType, nodeName, container);
  1063. this.attributes = Object.create(null);
  1064. this.style = null;
  1065. this.vShow = null;
  1066. this._html = null;
  1067. }
  1068. get className() {
  1069. return (this.attributes[ATTR_CLASS] || '');
  1070. }
  1071. set className(val) {
  1072. this.setAttribute(ATTR_CLASS, val);
  1073. }
  1074. get innerHTML() {
  1075. return '';
  1076. }
  1077. set innerHTML(html) {
  1078. this._html = html;
  1079. }
  1080. addEventListener(type, listener, options) {
  1081. super.addEventListener(type, listener, options);
  1082. if (this.pageNode && !this.pageNode.isUnmounted) {
  1083. if (listener.wxsEvent) {
  1084. this.pageNode.onAddWxsEvent(this, normalizeEventType(type, options), listener.wxsEvent, encodeModifier(listener.modifiers || []));
  1085. }
  1086. else {
  1087. this.pageNode.onAddEvent(this, normalizeEventType(type, options), encodeModifier(listener.modifiers || []));
  1088. }
  1089. }
  1090. }
  1091. removeEventListener(type, callback, options) {
  1092. super.removeEventListener(type, callback, options);
  1093. if (this.pageNode && !this.pageNode.isUnmounted) {
  1094. this.pageNode.onRemoveEvent(this, normalizeEventType(type, options));
  1095. }
  1096. }
  1097. getAttribute(qualifiedName) {
  1098. if (qualifiedName === ATTR_STYLE) {
  1099. return this.style;
  1100. }
  1101. return this.attributes[qualifiedName];
  1102. }
  1103. removeAttribute(qualifiedName) {
  1104. if (qualifiedName == ATTR_STYLE) {
  1105. this.style = null;
  1106. }
  1107. else {
  1108. delete this.attributes[qualifiedName];
  1109. }
  1110. if (this.pageNode && !this.pageNode.isUnmounted) {
  1111. this.pageNode.onRemoveAttribute(this, qualifiedName);
  1112. }
  1113. }
  1114. setAttribute(qualifiedName, value) {
  1115. if (qualifiedName === ATTR_STYLE) {
  1116. this.style = value;
  1117. }
  1118. else {
  1119. this.attributes[qualifiedName] = value;
  1120. }
  1121. if (this.pageNode && !this.pageNode.isUnmounted) {
  1122. this.pageNode.onSetAttribute(this, qualifiedName, value);
  1123. }
  1124. }
  1125. toJSON({ attr, normalize, } = {}) {
  1126. const { attributes, style, listeners, _text } = this;
  1127. const res = {};
  1128. if (Object.keys(attributes).length) {
  1129. res.a = normalize ? normalize(attributes) : attributes;
  1130. }
  1131. const events = Object.keys(listeners);
  1132. if (events.length) {
  1133. let w = undefined;
  1134. const e = {};
  1135. events.forEach((name) => {
  1136. const handlers = listeners[name];
  1137. if (handlers.length) {
  1138. // 可能存在多个 handler 且不同 modifiers 吗?
  1139. const { wxsEvent, modifiers } = handlers[0];
  1140. const modifier = encodeModifier(modifiers || []);
  1141. if (!wxsEvent) {
  1142. e[name] = modifier;
  1143. }
  1144. else {
  1145. if (!w) {
  1146. w = {};
  1147. }
  1148. w[name] = [normalize ? normalize(wxsEvent) : wxsEvent, modifier];
  1149. }
  1150. }
  1151. });
  1152. res.e = normalize ? normalize(e, false) : e;
  1153. if (w) {
  1154. res.w = normalize ? normalize(w, false) : w;
  1155. }
  1156. }
  1157. if (style !== null) {
  1158. res.s = normalize ? normalize(style) : style;
  1159. }
  1160. if (!attr) {
  1161. res.i = this.nodeId;
  1162. res.n = this.nodeName;
  1163. }
  1164. if (_text !== null) {
  1165. res.t = normalize ? normalize(_text) : _text;
  1166. }
  1167. return res;
  1168. }
  1169. }
  1170. class UniCommentNode extends UniNode {
  1171. constructor(text, container) {
  1172. super(NODE_TYPE_COMMENT, '#comment', container);
  1173. this._text = (process.env.NODE_ENV !== 'production') ? text : '';
  1174. }
  1175. toJSON(opts = {}) {
  1176. // 暂时不传递 text 到 view 层,没啥意义,节省点数据量
  1177. return opts.attr
  1178. ? {}
  1179. : {
  1180. i: this.nodeId,
  1181. };
  1182. // return opts.attr
  1183. // ? { t: this._text as string }
  1184. // : {
  1185. // i: this.nodeId!,
  1186. // t: this._text as string,
  1187. // }
  1188. }
  1189. }
  1190. class UniElement extends UniBaseNode {
  1191. constructor(nodeName, container) {
  1192. super(NODE_TYPE_ELEMENT, nodeName.toUpperCase(), container);
  1193. this.tagName = this.nodeName;
  1194. }
  1195. }
  1196. class UniInputElement extends UniElement {
  1197. get value() {
  1198. return this.getAttribute('value');
  1199. }
  1200. set value(val) {
  1201. this.setAttribute('value', val);
  1202. }
  1203. }
  1204. class UniTextAreaElement extends UniInputElement {
  1205. }
  1206. class UniTextNode extends UniBaseNode {
  1207. constructor(text, container) {
  1208. super(NODE_TYPE_TEXT, '#text', container);
  1209. this._text = text;
  1210. }
  1211. get nodeValue() {
  1212. return this._text || '';
  1213. }
  1214. set nodeValue(text) {
  1215. this._text = text;
  1216. if (this.pageNode && !this.pageNode.isUnmounted) {
  1217. this.pageNode.onNodeValue(this, text);
  1218. }
  1219. }
  1220. }
  1221. const forcePatchProps = {
  1222. AD: ['data'],
  1223. 'AD-DRAW': ['data'],
  1224. 'LIVE-PLAYER': ['picture-in-picture-mode'],
  1225. MAP: [
  1226. 'markers',
  1227. 'polyline',
  1228. 'circles',
  1229. 'controls',
  1230. 'include-points',
  1231. 'polygons',
  1232. ],
  1233. PICKER: ['range', 'value'],
  1234. 'PICKER-VIEW': ['value'],
  1235. 'RICH-TEXT': ['nodes'],
  1236. VIDEO: ['danmu-list', 'header'],
  1237. 'WEB-VIEW': ['webview-styles'],
  1238. };
  1239. const forcePatchPropKeys = ['animation'];
  1240. const forcePatchProp = (el, key) => {
  1241. if (forcePatchPropKeys.indexOf(key) > -1) {
  1242. return true;
  1243. }
  1244. const keys = forcePatchProps[el.nodeName];
  1245. if (keys && keys.indexOf(key) > -1) {
  1246. return true;
  1247. }
  1248. return false;
  1249. };
  1250. const ACTION_TYPE_PAGE_CREATE = 1;
  1251. const ACTION_TYPE_PAGE_CREATED = 2;
  1252. const ACTION_TYPE_CREATE = 3;
  1253. const ACTION_TYPE_INSERT = 4;
  1254. const ACTION_TYPE_REMOVE = 5;
  1255. const ACTION_TYPE_SET_ATTRIBUTE = 6;
  1256. const ACTION_TYPE_REMOVE_ATTRIBUTE = 7;
  1257. const ACTION_TYPE_ADD_EVENT = 8;
  1258. const ACTION_TYPE_REMOVE_EVENT = 9;
  1259. const ACTION_TYPE_SET_TEXT = 10;
  1260. const ACTION_TYPE_ADD_WXS_EVENT = 12;
  1261. const ACTION_TYPE_PAGE_SCROLL = 15;
  1262. const ACTION_TYPE_EVENT = 20;
  1263. /**
  1264. * 需要手动传入 timer,主要是解决 App 平台的定制 timer
  1265. */
  1266. function debounce(fn, delay, { clearTimeout, setTimeout }) {
  1267. let timeout;
  1268. const newFn = function () {
  1269. clearTimeout(timeout);
  1270. const timerFn = () => fn.apply(this, arguments);
  1271. timeout = setTimeout(timerFn, delay);
  1272. };
  1273. newFn.cancel = function () {
  1274. clearTimeout(timeout);
  1275. };
  1276. return newFn;
  1277. }
  1278. class EventChannel {
  1279. constructor(id, events) {
  1280. this.id = id;
  1281. this.listener = {};
  1282. this.emitCache = [];
  1283. if (events) {
  1284. Object.keys(events).forEach((name) => {
  1285. this.on(name, events[name]);
  1286. });
  1287. }
  1288. }
  1289. emit(eventName, ...args) {
  1290. const fns = this.listener[eventName];
  1291. if (!fns) {
  1292. return this.emitCache.push({
  1293. eventName,
  1294. args,
  1295. });
  1296. }
  1297. fns.forEach((opt) => {
  1298. opt.fn.apply(opt.fn, args);
  1299. });
  1300. this.listener[eventName] = fns.filter((opt) => opt.type !== 'once');
  1301. }
  1302. on(eventName, fn) {
  1303. this._addListener(eventName, 'on', fn);
  1304. this._clearCache(eventName);
  1305. }
  1306. once(eventName, fn) {
  1307. this._addListener(eventName, 'once', fn);
  1308. this._clearCache(eventName);
  1309. }
  1310. off(eventName, fn) {
  1311. const fns = this.listener[eventName];
  1312. if (!fns) {
  1313. return;
  1314. }
  1315. if (fn) {
  1316. for (let i = 0; i < fns.length;) {
  1317. if (fns[i].fn === fn) {
  1318. fns.splice(i, 1);
  1319. i--;
  1320. }
  1321. i++;
  1322. }
  1323. }
  1324. else {
  1325. delete this.listener[eventName];
  1326. }
  1327. }
  1328. _clearCache(eventName) {
  1329. for (let index = 0; index < this.emitCache.length; index++) {
  1330. const cache = this.emitCache[index];
  1331. const _name = eventName
  1332. ? cache.eventName === eventName
  1333. ? eventName
  1334. : null
  1335. : cache.eventName;
  1336. if (!_name)
  1337. continue;
  1338. const location = this.emit.apply(this, [_name, ...cache.args]);
  1339. if (typeof location === 'number') {
  1340. this.emitCache.pop();
  1341. continue;
  1342. }
  1343. this.emitCache.splice(index, 1);
  1344. index--;
  1345. }
  1346. }
  1347. _addListener(eventName, type, fn) {
  1348. (this.listener[eventName] || (this.listener[eventName] = [])).push({
  1349. fn,
  1350. type,
  1351. });
  1352. }
  1353. }
  1354. const PAGE_HOOKS = [
  1355. ON_INIT,
  1356. ON_LOAD,
  1357. ON_SHOW,
  1358. ON_HIDE,
  1359. ON_UNLOAD,
  1360. ON_BACK_PRESS,
  1361. ON_PAGE_SCROLL,
  1362. ON_TAB_ITEM_TAP,
  1363. ON_REACH_BOTTOM,
  1364. ON_PULL_DOWN_REFRESH,
  1365. ON_SHARE_TIMELINE,
  1366. ON_SHARE_APP_MESSAGE,
  1367. ON_ADD_TO_FAVORITES,
  1368. ON_SAVE_EXIT_STATE,
  1369. ON_NAVIGATION_BAR_BUTTON_TAP,
  1370. ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED,
  1371. ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED,
  1372. ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED,
  1373. ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED,
  1374. ];
  1375. const PAGE_SYNC_HOOKS = [ON_LOAD, ON_SHOW];
  1376. function isRootImmediateHook(name) {
  1377. return PAGE_SYNC_HOOKS.indexOf(name) > -1;
  1378. }
  1379. function isRootHook(name) {
  1380. return PAGE_HOOKS.indexOf(name) > -1;
  1381. }
  1382. const UniLifecycleHooks = [
  1383. ON_SHOW,
  1384. ON_HIDE,
  1385. ON_LAUNCH,
  1386. ON_ERROR,
  1387. ON_THEME_CHANGE,
  1388. ON_PAGE_NOT_FOUND,
  1389. ON_UNHANDLE_REJECTION,
  1390. ON_EXIT,
  1391. ON_INIT,
  1392. ON_LOAD,
  1393. ON_READY,
  1394. ON_UNLOAD,
  1395. ON_RESIZE,
  1396. ON_BACK_PRESS,
  1397. ON_PAGE_SCROLL,
  1398. ON_TAB_ITEM_TAP,
  1399. ON_REACH_BOTTOM,
  1400. ON_PULL_DOWN_REFRESH,
  1401. ON_SHARE_TIMELINE,
  1402. ON_ADD_TO_FAVORITES,
  1403. ON_SHARE_APP_MESSAGE,
  1404. ON_SAVE_EXIT_STATE,
  1405. ON_NAVIGATION_BAR_BUTTON_TAP,
  1406. ON_NAVIGATION_BAR_SEARCH_INPUT_CLICKED,
  1407. ON_NAVIGATION_BAR_SEARCH_INPUT_CHANGED,
  1408. ON_NAVIGATION_BAR_SEARCH_INPUT_CONFIRMED,
  1409. ON_NAVIGATION_BAR_SEARCH_INPUT_FOCUS_CHANGED,
  1410. ];
  1411. const MINI_PROGRAM_PAGE_RUNTIME_HOOKS = /*#__PURE__*/ (() => {
  1412. return {
  1413. onPageScroll: 1,
  1414. onShareAppMessage: 1 << 1,
  1415. onShareTimeline: 1 << 2,
  1416. };
  1417. })();
  1418. function isUniLifecycleHook(name, value, checkType = true) {
  1419. // 检查类型
  1420. if (checkType && !isFunction(value)) {
  1421. return false;
  1422. }
  1423. if (UniLifecycleHooks.indexOf(name) > -1) {
  1424. // 已预定义
  1425. return true;
  1426. }
  1427. else if (name.indexOf('on') === 0) {
  1428. // 以 on 开头
  1429. return true;
  1430. }
  1431. return false;
  1432. }
  1433. let vueApp;
  1434. const createVueAppHooks = [];
  1435. /**
  1436. * 提供 createApp 的回调事件,方便三方插件接收 App 对象,处理挂靠全局 mixin 之类的逻辑
  1437. */
  1438. function onCreateVueApp(hook) {
  1439. // TODO 每个 nvue 页面都会触发
  1440. if (vueApp) {
  1441. return hook(vueApp);
  1442. }
  1443. createVueAppHooks.push(hook);
  1444. }
  1445. function invokeCreateVueAppHook(app) {
  1446. vueApp = app;
  1447. createVueAppHooks.forEach((hook) => hook(app));
  1448. }
  1449. const invokeCreateErrorHandler = once((app, createErrorHandler) => {
  1450. if (isFunction(app._component.onError)) {
  1451. return createErrorHandler(app);
  1452. }
  1453. });
  1454. const E = function () {
  1455. // Keep this empty so it's easier to inherit from
  1456. // (via https://github.com/lipsmack from https://github.com/scottcorgan/tiny-emitter/issues/3)
  1457. };
  1458. E.prototype = {
  1459. on: function (name, callback, ctx) {
  1460. var e = this.e || (this.e = {});
  1461. (e[name] || (e[name] = [])).push({
  1462. fn: callback,
  1463. ctx: ctx,
  1464. });
  1465. return this;
  1466. },
  1467. once: function (name, callback, ctx) {
  1468. var self = this;
  1469. function listener() {
  1470. self.off(name, listener);
  1471. callback.apply(ctx, arguments);
  1472. }
  1473. listener._ = callback;
  1474. return this.on(name, listener, ctx);
  1475. },
  1476. emit: function (name) {
  1477. var data = [].slice.call(arguments, 1);
  1478. var evtArr = ((this.e || (this.e = {}))[name] || []).slice();
  1479. var i = 0;
  1480. var len = evtArr.length;
  1481. for (i; i < len; i++) {
  1482. evtArr[i].fn.apply(evtArr[i].ctx, data);
  1483. }
  1484. return this;
  1485. },
  1486. off: function (name, callback) {
  1487. var e = this.e || (this.e = {});
  1488. var evts = e[name];
  1489. var liveEvents = [];
  1490. if (evts && callback) {
  1491. for (var i = evts.length - 1; i >= 0; i--) {
  1492. if (evts[i].fn === callback || evts[i].fn._ === callback) {
  1493. evts.splice(i, 1);
  1494. break;
  1495. }
  1496. }
  1497. liveEvents = evts;
  1498. }
  1499. // Remove event from queue to prevent memory leak
  1500. // Suggested by https://github.com/lazd
  1501. // Ref: https://github.com/scottcorgan/tiny-emitter/commit/c6ebfaa9bc973b33d110a84a307742b7cf94c953#commitcomment-5024910
  1502. liveEvents.length ? (e[name] = liveEvents) : delete e[name];
  1503. return this;
  1504. },
  1505. };
  1506. var E$1 = E;
  1507. const borderStyles = {
  1508. black: 'rgba(0,0,0,0.4)',
  1509. white: 'rgba(255,255,255,0.4)',
  1510. };
  1511. function normalizeTabBarStyles(borderStyle) {
  1512. if (borderStyle && borderStyle in borderStyles) {
  1513. return borderStyles[borderStyle];
  1514. }
  1515. return borderStyle;
  1516. }
  1517. function normalizeTitleColor(titleColor) {
  1518. return titleColor === 'black' ? '#000000' : '#ffffff';
  1519. }
  1520. function normalizeStyles(pageStyle, themeConfig = {}, mode = 'light') {
  1521. const modeStyle = themeConfig[mode];
  1522. const styles = {};
  1523. if (!modeStyle) {
  1524. return pageStyle;
  1525. }
  1526. Object.keys(pageStyle).forEach((key) => {
  1527. let styleItem = pageStyle[key] // Object Array String
  1528. ;
  1529. styles[key] = (() => {
  1530. if (isPlainObject(styleItem)) {
  1531. return normalizeStyles(styleItem, themeConfig, mode);
  1532. }
  1533. else if (isArray(styleItem)) {
  1534. return styleItem.map((item) => isPlainObject(item)
  1535. ? normalizeStyles(item, themeConfig, mode)
  1536. : item);
  1537. }
  1538. else if (isString(styleItem) && styleItem.startsWith('@')) {
  1539. const _key = styleItem.replace('@', '');
  1540. let _styleItem = modeStyle[_key] || styleItem;
  1541. switch (key) {
  1542. case 'titleColor':
  1543. _styleItem = normalizeTitleColor(_styleItem);
  1544. break;
  1545. case 'borderStyle':
  1546. _styleItem = normalizeTabBarStyles(_styleItem);
  1547. break;
  1548. }
  1549. return _styleItem;
  1550. }
  1551. return styleItem;
  1552. })();
  1553. });
  1554. return styles;
  1555. }
  1556. function getEnvLocale() {
  1557. const { env } = process;
  1558. const lang = env.LC_ALL || env.LC_MESSAGES || env.LANG || env.LANGUAGE;
  1559. return (lang && lang.replace(/[.:].*/, '')) || 'en';
  1560. }
  1561. 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, OFF_THEME_CHANGE, ON_ADD_TO_FAVORITES, ON_APP_ENTER_BACKGROUND, ON_APP_ENTER_FOREGROUND, ON_BACK_PRESS, ON_ERROR, ON_EXIT, ON_HIDE, ON_INIT, ON_KEYBOARD_HEIGHT_CHANGE, ON_LAUNCH, ON_LOAD, ON_NAVIGATION_BAR_BUTTON_TAP, ON_NAVIGATION_BAR_CHANGE, 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_SAVE_EXIT_STATE, 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, UNI_UI_CONFLICT_TAGS, UVUE_BUILT_IN_TAGS, UVUE_IOS_BUILT_IN_TAGS, UVUE_WEB_BUILT_IN_TAGS, UniBaseNode, UniCommentNode, UniElement, UniEvent, UniInputElement, UniLifecycleHooks, UniNode, UniTextAreaElement, UniTextNode, WEB_INVOKE_APPSERVICE, WXS_MODULES, WXS_PROTOCOL, addFont, addLeadingSlash, borderStyles, cache, cacheStringFunction, callOptions, createIsCustomElement, createRpx2Unit, createUniEvent, customizeEvent, debounce, decode, decodedQuery, defaultMiniProgramRpx2Unit, defaultNVueRpx2Unit, defaultRpx2Unit, dynamicSlotName, forcePatchProp, formatDateTime, formatLog, getCustomDataset, getEnvLocale, getLen, getValueByDataPath, initCustomDatasetOnce, invokeArrayFns, invokeCreateErrorHandler, invokeCreateVueAppHook, isAppNVueNativeTag, isAppNativeTag, isAppUVueNativeTag, isBuiltInComponent, isComponentInternalInstance, isComponentTag, isH5CustomElement, isH5NativeTag, isMiniProgramNativeTag, isRootHook, isRootImmediateHook, isUniLifecycleHook, isUniXElement, normalizeClass, normalizeDataset, normalizeEventType, normalizeProps, normalizeStyle, normalizeStyles, normalizeTabBarStyles, normalizeTarget, normalizeTitleColor, onCreateVueApp, once, parseEventName, parseNVueDataset, parseQuery, parseUrl, passive, plusReady, removeLeadingSlash, resolveComponentInstance, resolveOwnerEl, resolveOwnerVm, sanitise, scrollTo, sortObject, stringifyQuery, updateElementStyle };