uni.mp.esm.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  1. import { SLOT_DEFAULT_NAME, EventChannel, invokeArrayFns, MINI_PROGRAM_PAGE_RUNTIME_HOOKS, ON_LOAD, ON_SHOW, ON_HIDE, ON_UNLOAD, ON_RESIZE, ON_TAB_ITEM_TAP, ON_REACH_BOTTOM, ON_PULL_DOWN_REFRESH, ON_ADD_TO_FAVORITES, isUniLifecycleHook, ON_READY, once, ON_LAUNCH, ON_ERROR, ON_THEME_CHANGE, ON_PAGE_NOT_FOUND, ON_UNHANDLE_REJECTION, customizeEvent, addLeadingSlash, stringifyQuery } from '@dcloudio/uni-shared';
  2. import { isArray, isFunction, hasOwn, extend, isPlainObject } from '@vue/shared';
  3. import { ref, nextTick, findComponentPropsData, toRaw, updateProps, hasQueueJob, invalidateJob, getExposeProxy, pruneComponentPropsCache } from 'vue';
  4. import { normalizeLocale, LOCALE_EN } from '@dcloudio/uni-i18n';
  5. const MP_METHODS = [
  6. 'createSelectorQuery',
  7. 'createIntersectionObserver',
  8. 'selectAllComponents',
  9. 'selectComponent',
  10. ];
  11. function createEmitFn(oldEmit, ctx) {
  12. return function emit(event, ...args) {
  13. const scope = ctx.$scope;
  14. if (scope && event) {
  15. const detail = { __args__: args };
  16. {
  17. (scope._triggerEvent || scope.triggerEvent)(event, detail);
  18. }
  19. }
  20. return oldEmit.apply(this, [event, ...args]);
  21. };
  22. }
  23. function initBaseInstance(instance, options) {
  24. const ctx = instance.ctx;
  25. // mp
  26. ctx.mpType = options.mpType; // @deprecated
  27. ctx.$mpType = options.mpType;
  28. ctx.$mpPlatform = "mp-jd";
  29. ctx.$scope = options.mpInstance;
  30. // TODO @deprecated
  31. ctx.$mp = {};
  32. if (__VUE_OPTIONS_API__) {
  33. ctx._self = {};
  34. }
  35. // slots
  36. instance.slots = {};
  37. if (isArray(options.slots) && options.slots.length) {
  38. options.slots.forEach((name) => {
  39. instance.slots[name] = true;
  40. });
  41. if (instance.slots[SLOT_DEFAULT_NAME]) {
  42. instance.slots.default = true;
  43. }
  44. }
  45. ctx.getOpenerEventChannel = function () {
  46. if (!this.__eventChannel__) {
  47. this.__eventChannel__ = new EventChannel();
  48. }
  49. return this.__eventChannel__;
  50. };
  51. ctx.$hasHook = hasHook;
  52. ctx.$callHook = callHook;
  53. // $emit
  54. instance.emit = createEmitFn(instance.emit, ctx);
  55. }
  56. function initComponentInstance(instance, options) {
  57. initBaseInstance(instance, options);
  58. const ctx = instance.ctx;
  59. MP_METHODS.forEach((method) => {
  60. ctx[method] = function (...args) {
  61. const mpInstance = ctx.$scope;
  62. if (mpInstance && mpInstance[method]) {
  63. return mpInstance[method].apply(mpInstance, args);
  64. }
  65. };
  66. });
  67. }
  68. function initMocks(instance, mpInstance, mocks) {
  69. const ctx = instance.ctx;
  70. mocks.forEach((mock) => {
  71. if (hasOwn(mpInstance, mock)) {
  72. instance[mock] = ctx[mock] = mpInstance[mock];
  73. }
  74. });
  75. }
  76. function hasHook(name) {
  77. const hooks = this.$[name];
  78. if (hooks && hooks.length) {
  79. return true;
  80. }
  81. return false;
  82. }
  83. function callHook(name, args) {
  84. if (name === 'mounted') {
  85. callHook.call(this, 'bm'); // beforeMount
  86. this.$.isMounted = true;
  87. name = 'm';
  88. }
  89. {
  90. if (name === 'onLoad' &&
  91. args &&
  92. args.__id__ &&
  93. isFunction(jd.getEventChannel)) {
  94. this.__eventChannel__ = jd.getEventChannel(args.__id__);
  95. delete args.__id__;
  96. }
  97. }
  98. const hooks = this.$[name];
  99. return hooks && invokeArrayFns(hooks, args);
  100. }
  101. const PAGE_INIT_HOOKS = [
  102. ON_LOAD,
  103. ON_SHOW,
  104. ON_HIDE,
  105. ON_UNLOAD,
  106. ON_RESIZE,
  107. ON_TAB_ITEM_TAP,
  108. ON_REACH_BOTTOM,
  109. ON_PULL_DOWN_REFRESH,
  110. ON_ADD_TO_FAVORITES,
  111. // 'onReady', // lifetimes.ready
  112. // 'onPageScroll', // 影响性能,开发者手动注册
  113. // 'onShareTimeline', // 右上角菜单,开发者手动注册
  114. // 'onShareAppMessage' // 右上角菜单,开发者手动注册
  115. ];
  116. function findHooks(vueOptions, hooks = new Set()) {
  117. if (vueOptions) {
  118. Object.keys(vueOptions).forEach((name) => {
  119. if (isUniLifecycleHook(name, vueOptions[name])) {
  120. hooks.add(name);
  121. }
  122. });
  123. if (__VUE_OPTIONS_API__) {
  124. const { extends: extendsOptions, mixins } = vueOptions;
  125. if (mixins) {
  126. mixins.forEach((mixin) => findHooks(mixin, hooks));
  127. }
  128. if (extendsOptions) {
  129. findHooks(extendsOptions, hooks);
  130. }
  131. }
  132. }
  133. return hooks;
  134. }
  135. function initHook(mpOptions, hook, excludes) {
  136. if (excludes.indexOf(hook) === -1 && !hasOwn(mpOptions, hook)) {
  137. mpOptions[hook] = function (args) {
  138. return this.$vm && this.$vm.$callHook(hook, args);
  139. };
  140. }
  141. }
  142. const EXCLUDE_HOOKS = [ON_READY];
  143. function initHooks(mpOptions, hooks, excludes = EXCLUDE_HOOKS) {
  144. hooks.forEach((hook) => initHook(mpOptions, hook, excludes));
  145. }
  146. function initUnknownHooks(mpOptions, vueOptions, excludes = EXCLUDE_HOOKS) {
  147. findHooks(vueOptions).forEach((hook) => initHook(mpOptions, hook, excludes));
  148. }
  149. function initRuntimeHooks(mpOptions, runtimeHooks) {
  150. if (!runtimeHooks) {
  151. return;
  152. }
  153. const hooks = Object.keys(MINI_PROGRAM_PAGE_RUNTIME_HOOKS);
  154. hooks.forEach((hook) => {
  155. if (runtimeHooks & MINI_PROGRAM_PAGE_RUNTIME_HOOKS[hook]) {
  156. initHook(mpOptions, hook, []);
  157. }
  158. });
  159. }
  160. const findMixinRuntimeHooks = /*#__PURE__*/ once(() => {
  161. const runtimeHooks = [];
  162. const app = isFunction(getApp) && getApp({ allowDefault: true });
  163. if (app && app.$vm && app.$vm.$) {
  164. const mixins = app.$vm.$.appContext.mixins;
  165. if (isArray(mixins)) {
  166. const hooks = Object.keys(MINI_PROGRAM_PAGE_RUNTIME_HOOKS);
  167. mixins.forEach((mixin) => {
  168. hooks.forEach((hook) => {
  169. if (hasOwn(mixin, hook) && !runtimeHooks.includes(hook)) {
  170. runtimeHooks.push(hook);
  171. }
  172. });
  173. });
  174. }
  175. }
  176. return runtimeHooks;
  177. });
  178. function initMixinRuntimeHooks(mpOptions) {
  179. initHooks(mpOptions, findMixinRuntimeHooks());
  180. }
  181. const HOOKS = [
  182. ON_SHOW,
  183. ON_HIDE,
  184. ON_ERROR,
  185. ON_THEME_CHANGE,
  186. ON_PAGE_NOT_FOUND,
  187. ON_UNHANDLE_REJECTION,
  188. ];
  189. function parseApp(instance, parseAppOptions) {
  190. const internalInstance = instance.$;
  191. if (__VUE_PROD_DEVTOOLS__) {
  192. // 定制 App 的 $children
  193. Object.defineProperty(internalInstance.ctx, '$children', {
  194. get() {
  195. return getCurrentPages().map((page) => page.$vm);
  196. },
  197. });
  198. }
  199. const appOptions = {
  200. globalData: (instance.$options && instance.$options.globalData) || {},
  201. $vm: instance,
  202. onLaunch(options) {
  203. this.$vm = instance; // 飞书小程序可能会把 AppOptions 序列化,导致 $vm 对象部分属性丢失
  204. const ctx = internalInstance.ctx;
  205. if (this.$vm && ctx.$scope) {
  206. // 已经初始化过了,主要是为了百度,百度 onShow 在 onLaunch 之前
  207. return;
  208. }
  209. initBaseInstance(internalInstance, {
  210. mpType: 'app',
  211. mpInstance: this,
  212. slots: [],
  213. });
  214. ctx.globalData = this.globalData;
  215. instance.$callHook(ON_LAUNCH, options);
  216. },
  217. };
  218. const { onError } = internalInstance;
  219. if (onError) {
  220. internalInstance.appContext.config.errorHandler = (err) => {
  221. instance.$callHook(ON_ERROR, err);
  222. };
  223. }
  224. initLocale(instance);
  225. const vueOptions = instance.$.type;
  226. initHooks(appOptions, HOOKS);
  227. initUnknownHooks(appOptions, vueOptions);
  228. if (__VUE_OPTIONS_API__) {
  229. const methods = vueOptions.methods;
  230. methods && extend(appOptions, methods);
  231. }
  232. if (parseAppOptions) {
  233. parseAppOptions.parse(appOptions);
  234. }
  235. return appOptions;
  236. }
  237. function initCreateApp(parseAppOptions) {
  238. return function createApp(vm) {
  239. return App(parseApp(vm, parseAppOptions));
  240. };
  241. }
  242. function initCreateSubpackageApp(parseAppOptions) {
  243. return function createApp(vm) {
  244. const appOptions = parseApp(vm, parseAppOptions);
  245. const app = isFunction(getApp) &&
  246. getApp({
  247. allowDefault: true,
  248. });
  249. if (!app)
  250. return;
  251. vm.$.ctx.$scope = app;
  252. const globalData = app.globalData;
  253. if (globalData) {
  254. Object.keys(appOptions.globalData).forEach((name) => {
  255. if (!hasOwn(globalData, name)) {
  256. globalData[name] = appOptions.globalData[name];
  257. }
  258. });
  259. }
  260. Object.keys(appOptions).forEach((name) => {
  261. if (!hasOwn(app, name)) {
  262. app[name] = appOptions[name];
  263. }
  264. });
  265. initAppLifecycle(appOptions, vm);
  266. if (process.env.UNI_SUBPACKAGE) {
  267. (jd.$subpackages || (jd.$subpackages = {}))[process.env.UNI_SUBPACKAGE] = {
  268. $vm: vm,
  269. };
  270. }
  271. };
  272. }
  273. function initAppLifecycle(appOptions, vm) {
  274. if (isFunction(appOptions.onLaunch)) {
  275. const args = jd.getLaunchOptionsSync && jd.getLaunchOptionsSync();
  276. appOptions.onLaunch(args);
  277. }
  278. if (isFunction(appOptions.onShow) && jd.onAppShow) {
  279. jd.onAppShow((args) => {
  280. vm.$callHook('onShow', args);
  281. });
  282. }
  283. if (isFunction(appOptions.onHide) && jd.onAppHide) {
  284. jd.onAppHide((args) => {
  285. vm.$callHook('onHide', args);
  286. });
  287. }
  288. }
  289. function initLocale(appVm) {
  290. const locale = ref(normalizeLocale(jd.getSystemInfoSync().language) || LOCALE_EN);
  291. Object.defineProperty(appVm, '$locale', {
  292. get() {
  293. return locale.value;
  294. },
  295. set(v) {
  296. locale.value = v;
  297. },
  298. });
  299. }
  300. function initVueIds(vueIds, mpInstance) {
  301. if (!vueIds) {
  302. return;
  303. }
  304. const ids = vueIds.split(',');
  305. const len = ids.length;
  306. if (len === 1) {
  307. mpInstance._$vueId = ids[0];
  308. }
  309. else if (len === 2) {
  310. mpInstance._$vueId = ids[0];
  311. mpInstance._$vuePid = ids[1];
  312. }
  313. }
  314. function initWxsCallMethods(methods, wxsCallMethods) {
  315. if (!isArray(wxsCallMethods)) {
  316. return;
  317. }
  318. wxsCallMethods.forEach((callMethod) => {
  319. methods[callMethod] = function (args) {
  320. return this.$vm[callMethod](args);
  321. };
  322. });
  323. }
  324. function selectAllComponents(mpInstance, selector, $refs) {
  325. const components = mpInstance.selectAllComponents(selector);
  326. components.forEach((component) => {
  327. const ref = component.properties.uR;
  328. $refs[ref] = component.$vm || component;
  329. });
  330. }
  331. function initRefs(instance, mpInstance) {
  332. Object.defineProperty(instance, 'refs', {
  333. get() {
  334. const $refs = {};
  335. selectAllComponents(mpInstance, '.r', $refs);
  336. const forComponents = mpInstance.selectAllComponents('.r-i-f');
  337. forComponents.forEach((component) => {
  338. const ref = component.properties.uR;
  339. if (!ref) {
  340. return;
  341. }
  342. if (!$refs[ref]) {
  343. $refs[ref] = [];
  344. }
  345. $refs[ref].push(component.$vm || component);
  346. });
  347. return $refs;
  348. },
  349. });
  350. }
  351. function findVmByVueId(instance, vuePid) {
  352. // 标准 vue3 中 没有 $children,定制了内核
  353. const $children = instance.$children;
  354. // 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200)
  355. for (let i = $children.length - 1; i >= 0; i--) {
  356. const childVm = $children[i];
  357. if (childVm.$scope._$vueId === vuePid) {
  358. return childVm;
  359. }
  360. }
  361. // 反向递归查找
  362. let parentVm;
  363. for (let i = $children.length - 1; i >= 0; i--) {
  364. parentVm = findVmByVueId($children[i], vuePid);
  365. if (parentVm) {
  366. return parentVm;
  367. }
  368. }
  369. }
  370. function nextSetDataTick(mpInstance, fn) {
  371. // 随便设置一个字段来触发回调(部分平台必须有字段才可以,比如头条)
  372. mpInstance.setData({ r1: 1 }, () => fn());
  373. }
  374. function initSetRef(mpInstance) {
  375. if (!mpInstance._$setRef) {
  376. mpInstance._$setRef = (fn) => {
  377. nextTick(() => nextSetDataTick(mpInstance, fn));
  378. };
  379. }
  380. }
  381. const builtInProps = [
  382. // 百度小程序,快手小程序自定义组件不支持绑定动态事件,动态dataset,故通过props传递事件信息
  383. // event-opts
  384. 'eO',
  385. // 组件 ref
  386. 'uR',
  387. // 组件 ref-in-for
  388. 'uRIF',
  389. // 组件 id
  390. 'uI',
  391. // 组件类型 m: 小程序组件
  392. 'uT',
  393. // 组件 props
  394. 'uP',
  395. // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
  396. 'uS',
  397. ];
  398. function initDefaultProps(options, isBehavior = false) {
  399. const properties = {};
  400. if (!isBehavior) {
  401. // 均不指定类型,避免微信小程序 property received type-uncompatible value 警告
  402. builtInProps.forEach((name) => {
  403. properties[name] = {
  404. type: null,
  405. value: '',
  406. };
  407. });
  408. // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
  409. properties.uS = {
  410. type: null,
  411. value: [],
  412. observer: function (newVal) {
  413. const $slots = Object.create(null);
  414. newVal &&
  415. newVal.forEach((slotName) => {
  416. $slots[slotName] = true;
  417. });
  418. this.setData({
  419. $slots,
  420. });
  421. },
  422. };
  423. }
  424. if (options.behaviors) {
  425. // wx://form-field
  426. if (options.behaviors.includes('jd://form-field')) {
  427. if (!options.properties || !options.properties.name) {
  428. properties.name = {
  429. type: null,
  430. value: '',
  431. };
  432. }
  433. if (!options.properties || !options.properties.value) {
  434. properties.value = {
  435. type: null,
  436. value: '',
  437. };
  438. }
  439. }
  440. }
  441. return properties;
  442. }
  443. function initVirtualHostProps(options) {
  444. const properties = {};
  445. return properties;
  446. }
  447. /**
  448. *
  449. * @param mpComponentOptions
  450. * @param isBehavior
  451. */
  452. function initProps(mpComponentOptions) {
  453. if (!mpComponentOptions.properties) {
  454. mpComponentOptions.properties = {};
  455. }
  456. extend(mpComponentOptions.properties, initDefaultProps(mpComponentOptions), initVirtualHostProps(mpComponentOptions.options));
  457. }
  458. const PROP_TYPES = [String, Number, Boolean, Object, Array, null];
  459. function parsePropType(type, defaultValue) {
  460. // [String]=>String
  461. if (isArray(type) && type.length === 1) {
  462. return type[0];
  463. }
  464. return type;
  465. }
  466. function normalizePropType(type, defaultValue) {
  467. const res = parsePropType(type);
  468. return PROP_TYPES.indexOf(res) !== -1 ? res : null;
  469. }
  470. /**
  471. * 初始化页面 props,方便接收页面参数,类型均为String,默认值均为''
  472. * @param param
  473. * @param rawProps
  474. */
  475. function initPageProps({ properties }, rawProps) {
  476. if (isArray(rawProps)) {
  477. rawProps.forEach((key) => {
  478. properties[key] = {
  479. type: String,
  480. value: '',
  481. };
  482. });
  483. }
  484. else if (isPlainObject(rawProps)) {
  485. Object.keys(rawProps).forEach((key) => {
  486. const opts = rawProps[key];
  487. if (isPlainObject(opts)) {
  488. // title:{type:String,default:''}
  489. let value = opts.default;
  490. if (isFunction(value)) {
  491. value = value();
  492. }
  493. const type = opts.type;
  494. opts.type = normalizePropType(type);
  495. properties[key] = {
  496. type: opts.type,
  497. value,
  498. };
  499. }
  500. else {
  501. // content:String
  502. properties[key] = {
  503. type: normalizePropType(opts),
  504. };
  505. }
  506. });
  507. }
  508. }
  509. function findPropsData(properties, isPage) {
  510. return ((isPage
  511. ? findPagePropsData(properties)
  512. : findComponentPropsData(properties.uP)) || {});
  513. }
  514. function findPagePropsData(properties) {
  515. const propsData = {};
  516. if (isPlainObject(properties)) {
  517. Object.keys(properties).forEach((name) => {
  518. if (builtInProps.indexOf(name) === -1) {
  519. propsData[name] = properties[name];
  520. }
  521. });
  522. }
  523. return propsData;
  524. }
  525. function initFormField(vm) {
  526. // 同步 form-field 的 name,value 值
  527. const vueOptions = vm.$options;
  528. if (isArray(vueOptions.behaviors) &&
  529. vueOptions.behaviors.includes('uni://form-field')) {
  530. vm.$watch('modelValue', () => {
  531. vm.$scope &&
  532. vm.$scope.setData({
  533. name: vm.name,
  534. value: vm.modelValue,
  535. });
  536. }, {
  537. immediate: true,
  538. });
  539. }
  540. }
  541. function initData(_) {
  542. return {};
  543. }
  544. function initPropsObserver(componentOptions) {
  545. const observe = function observe() {
  546. const up = this.properties.uP;
  547. if (!up) {
  548. return;
  549. }
  550. if (this.$vm) {
  551. updateComponentProps(up, this.$vm.$);
  552. }
  553. else if (this.properties.uT === 'm') {
  554. // 小程序组件
  555. updateMiniProgramComponentProperties(up, this);
  556. }
  557. };
  558. {
  559. componentOptions.properties.uP.observer = observe;
  560. }
  561. }
  562. function updateMiniProgramComponentProperties(up, mpInstance) {
  563. const prevProps = mpInstance.properties;
  564. const nextProps = findComponentPropsData(up) || {};
  565. if (hasPropsChanged(prevProps, nextProps, false)) {
  566. mpInstance.setData(nextProps);
  567. }
  568. }
  569. function updateComponentProps(up, instance) {
  570. const prevProps = toRaw(instance.props);
  571. const nextProps = findComponentPropsData(up) || {};
  572. if (hasPropsChanged(prevProps, nextProps)) {
  573. updateProps(instance, nextProps, prevProps, false);
  574. if (hasQueueJob(instance.update)) {
  575. invalidateJob(instance.update);
  576. }
  577. {
  578. instance.update();
  579. }
  580. }
  581. }
  582. function hasPropsChanged(prevProps, nextProps, checkLen = true) {
  583. const nextKeys = Object.keys(nextProps);
  584. if (checkLen && nextKeys.length !== Object.keys(prevProps).length) {
  585. return true;
  586. }
  587. for (let i = 0; i < nextKeys.length; i++) {
  588. const key = nextKeys[i];
  589. if (nextProps[key] !== prevProps[key]) {
  590. return true;
  591. }
  592. }
  593. return false;
  594. }
  595. function initBehaviors(vueOptions) {
  596. const vueBehaviors = vueOptions.behaviors;
  597. let vueProps = vueOptions.props;
  598. if (!vueProps) {
  599. vueOptions.props = vueProps = [];
  600. }
  601. const behaviors = [];
  602. if (isArray(vueBehaviors)) {
  603. vueBehaviors.forEach((behavior) => {
  604. behaviors.push(behavior.replace('uni://', 'jd://'));
  605. if (behavior === 'uni://form-field') {
  606. if (isArray(vueProps)) {
  607. vueProps.push('name');
  608. vueProps.push('modelValue');
  609. }
  610. else {
  611. vueProps.name = {
  612. type: String,
  613. default: '',
  614. };
  615. vueProps.modelValue = {
  616. type: [String, Number, Boolean, Array, Object, Date],
  617. default: '',
  618. };
  619. }
  620. }
  621. });
  622. }
  623. return behaviors;
  624. }
  625. let $createComponentFn;
  626. let $destroyComponentFn;
  627. function getAppVm() {
  628. if (process.env.UNI_MP_PLUGIN) {
  629. return jd.$vm;
  630. }
  631. if (process.env.UNI_SUBPACKAGE) {
  632. return jd.$subpackages[process.env.UNI_SUBPACKAGE].$vm;
  633. }
  634. return getApp().$vm;
  635. }
  636. function $createComponent(initialVNode, options) {
  637. if (!$createComponentFn) {
  638. $createComponentFn = getAppVm().$createComponent;
  639. }
  640. const proxy = $createComponentFn(initialVNode, options);
  641. return getExposeProxy(proxy.$) || proxy;
  642. }
  643. function $destroyComponent(instance) {
  644. if (!$destroyComponentFn) {
  645. $destroyComponentFn = getAppVm().$destroyComponent;
  646. }
  647. return $destroyComponentFn(instance);
  648. }
  649. const MPPage = Page;
  650. const MPComponent = Component;
  651. function initTriggerEvent(mpInstance) {
  652. const oldTriggerEvent = mpInstance.triggerEvent;
  653. const newTriggerEvent = function (event, ...args) {
  654. return oldTriggerEvent.apply(mpInstance, [customizeEvent(event), ...args]);
  655. };
  656. // 京东小程序triggerEvent为只读属性
  657. try {
  658. mpInstance.triggerEvent = newTriggerEvent;
  659. }
  660. catch (error) {
  661. mpInstance._triggerEvent = newTriggerEvent;
  662. }
  663. }
  664. function initMiniProgramHook(name, options, isComponent) {
  665. const oldHook = options[name];
  666. if (!oldHook) {
  667. options[name] = function () {
  668. initTriggerEvent(this);
  669. };
  670. }
  671. else {
  672. options[name] = function (...args) {
  673. initTriggerEvent(this);
  674. return oldHook.apply(this, args);
  675. };
  676. }
  677. }
  678. Page = function (options) {
  679. initMiniProgramHook(ON_LOAD, options);
  680. return MPPage(options);
  681. };
  682. Component = function (options) {
  683. initMiniProgramHook('created', options);
  684. // 小程序组件
  685. const isVueComponent = options.properties && options.properties.uP;
  686. if (!isVueComponent) {
  687. initProps(options);
  688. initPropsObserver(options);
  689. }
  690. return MPComponent(options);
  691. };
  692. // @ts-ignore
  693. function initLifetimes({ mocks, isPage, initRelation, vueOptions, }) {
  694. return {
  695. attached() {
  696. // 微信 和 QQ 不需要延迟 setRef
  697. {
  698. initSetRef(this);
  699. }
  700. let properties = this.properties;
  701. initVueIds(properties.uI, this);
  702. const relationOptions = {
  703. vuePid: this._$vuePid,
  704. };
  705. // 处理父子关系
  706. initRelation(this, relationOptions);
  707. // 初始化 vue 实例
  708. const mpInstance = this;
  709. const isMiniProgramPage = isPage(mpInstance);
  710. let propsData = properties;
  711. this.$vm = $createComponent({
  712. type: vueOptions,
  713. props: findPropsData(propsData, isMiniProgramPage),
  714. }, {
  715. mpType: isMiniProgramPage ? 'page' : 'component',
  716. mpInstance,
  717. slots: properties.uS || {},
  718. parentComponent: relationOptions.parent && relationOptions.parent.$,
  719. onBeforeSetup(instance, options) {
  720. initRefs(instance, mpInstance);
  721. initMocks(instance, mpInstance, mocks);
  722. initComponentInstance(instance, options);
  723. },
  724. });
  725. if (!isMiniProgramPage) {
  726. initFormField(this.$vm);
  727. }
  728. },
  729. ready() {
  730. // 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
  731. // https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
  732. if (this.$vm) {
  733. {
  734. nextSetDataTick(this, () => {
  735. this.$vm.$callHook('mounted');
  736. this.$vm.$callHook(ON_READY);
  737. });
  738. }
  739. }
  740. },
  741. detached() {
  742. if (this.$vm) {
  743. pruneComponentPropsCache(this.$vm.$.uid);
  744. $destroyComponent(this.$vm);
  745. }
  746. },
  747. };
  748. }
  749. const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__'];
  750. function isPage(mpInstance) {
  751. return !!mpInstance.route;
  752. }
  753. function initRelation$1(mpInstance, detail) {
  754. mpInstance.triggerEvent('__l', detail);
  755. }
  756. function handleLink(event) {
  757. // detail 是微信,value 是百度(dipatch)
  758. const detail = (event.detail ||
  759. event.value);
  760. const vuePid = detail.vuePid;
  761. let parentVm;
  762. if (vuePid) {
  763. parentVm = findVmByVueId(this.$vm, vuePid);
  764. }
  765. if (!parentVm) {
  766. parentVm = this.$vm;
  767. }
  768. detail.parent = parentVm;
  769. }
  770. var baseParseOptions = /*#__PURE__*/Object.freeze({
  771. __proto__: null,
  772. handleLink: handleLink,
  773. initLifetimes: initLifetimes,
  774. initRelation: initRelation$1,
  775. isPage: isPage,
  776. mocks: mocks
  777. });
  778. const createApp = initCreateApp();
  779. const createSubpackageApp = initCreateSubpackageApp();
  780. function applyOptions(componentOptions, vueOptions) {
  781. componentOptions.data = initData();
  782. componentOptions.behaviors = initBehaviors(vueOptions);
  783. }
  784. const EXTRAS = ['externalClasses'];
  785. function initExtraOptions(miniProgramComponentOptions, vueOptions) {
  786. EXTRAS.forEach((name) => {
  787. if (hasOwn(vueOptions, name)) {
  788. miniProgramComponentOptions[name] = vueOptions[name];
  789. }
  790. });
  791. }
  792. function parseComponent(vueOptions, { parse, mocks, isPage, initRelation, handleLink, initLifetimes, }) {
  793. vueOptions = vueOptions.default || vueOptions;
  794. const options = {
  795. multipleSlots: true,
  796. addGlobalClass: true,
  797. pureDataPattern: /^uP$/,
  798. };
  799. if (vueOptions.options) {
  800. extend(options, vueOptions.options);
  801. }
  802. const mpComponentOptions = {
  803. options,
  804. pageLifetimes: {
  805. show() {
  806. this.$vm && this.$vm.$callHook('onPageShow');
  807. },
  808. hide() {
  809. this.$vm && this.$vm.$callHook('onPageHide');
  810. },
  811. resize(size) {
  812. this.$vm && this.$vm.$callHook('onPageResize', size);
  813. },
  814. },
  815. methods: {
  816. __l: handleLink,
  817. },
  818. };
  819. // 京东不支持在lifetimes中声明周期,故提取到最外层
  820. extend(mpComponentOptions, initLifetimes({ mocks, isPage, initRelation, vueOptions }));
  821. if (__VUE_OPTIONS_API__) {
  822. applyOptions(mpComponentOptions, vueOptions);
  823. }
  824. initProps(mpComponentOptions);
  825. initPropsObserver(mpComponentOptions);
  826. initExtraOptions(mpComponentOptions, vueOptions);
  827. initWxsCallMethods(mpComponentOptions.methods, vueOptions.wxsCallMethods);
  828. if (parse) {
  829. parse(mpComponentOptions, { handleLink });
  830. }
  831. return mpComponentOptions;
  832. }
  833. function initCreateComponent(parseOptions) {
  834. return function createComponent(vueComponentOptions) {
  835. return Component(parseComponent(vueComponentOptions, parseOptions));
  836. };
  837. }
  838. function parsePage(vueOptions, parseOptions) {
  839. const { parse, mocks, isPage, initRelation, handleLink, initLifetimes } = parseOptions;
  840. const miniProgramPageOptions = parseComponent(vueOptions, {
  841. mocks,
  842. isPage,
  843. initRelation,
  844. handleLink,
  845. initLifetimes,
  846. });
  847. initPageProps(miniProgramPageOptions, (vueOptions.default || vueOptions).props);
  848. const methods = miniProgramPageOptions.methods;
  849. methods.onLoad = function (query) {
  850. this.options = query;
  851. this.$page = {
  852. fullPath: addLeadingSlash(this.route + stringifyQuery(query)),
  853. };
  854. return this.$vm && this.$vm.$callHook(ON_LOAD, query);
  855. };
  856. initHooks(methods, PAGE_INIT_HOOKS);
  857. initUnknownHooks(methods, vueOptions);
  858. initRuntimeHooks(methods, vueOptions.__runtimeHooks);
  859. initMixinRuntimeHooks(methods);
  860. parse && parse(miniProgramPageOptions, { handleLink });
  861. return miniProgramPageOptions;
  862. }
  863. function initCreatePage(parseOptions) {
  864. return function createPage(vuePageOptions) {
  865. return Component(parsePage(vuePageOptions, parseOptions));
  866. };
  867. }
  868. function initRelation(mpInstance, detail) {
  869. // 兼容triggerEvent
  870. // @ts-ignore
  871. mpInstance._triggerEvent('__l', detail);
  872. }
  873. var parseOptions = extend({}, baseParseOptions, {
  874. initRelation,
  875. });
  876. const createComponent = initCreateComponent(parseOptions);
  877. const createPage = initCreatePage(parseOptions);
  878. jd.EventChannel = EventChannel;
  879. jd.createApp = global.createApp = createApp;
  880. jd.createPage = createPage;
  881. jd.createComponent = createComponent;
  882. jd.createSubpackageApp = global.createSubpackageApp =
  883. createSubpackageApp;
  884. export { createComponent };