uni.mp.esm.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  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, addLeadingSlash, stringifyQuery, customizeEvent } from '@dcloudio/uni-shared';
  2. import { isArray, isFunction, hasOwn, extend, isPlainObject, isObject } from '@vue/shared';
  3. import { ref, findComponentPropsData, toRaw, updateProps, hasQueueJob, invalidateJob, devtoolsComponentAdded, 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(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-qq";
  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(qq.getEventChannel)) {
  94. this.__eventChannel__ = qq.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. (qq.$subpackages || (qq.$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 = qq.getLaunchOptionsSync && qq.getLaunchOptionsSync();
  276. appOptions.onLaunch(args);
  277. }
  278. if (isFunction(appOptions.onShow) && qq.onAppShow) {
  279. qq.onAppShow((args) => {
  280. vm.$callHook('onShow', args);
  281. });
  282. }
  283. if (isFunction(appOptions.onHide) && qq.onAppHide) {
  284. qq.onAppHide((args) => {
  285. vm.$callHook('onHide', args);
  286. });
  287. }
  288. }
  289. function initLocale(appVm) {
  290. const locale = ref(normalizeLocale(qq.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. const EXTRAS = ['externalClasses'];
  315. function initExtraOptions(miniProgramComponentOptions, vueOptions) {
  316. EXTRAS.forEach((name) => {
  317. if (hasOwn(vueOptions, name)) {
  318. miniProgramComponentOptions[name] = vueOptions[name];
  319. }
  320. });
  321. }
  322. function initWxsCallMethods(methods, wxsCallMethods) {
  323. if (!isArray(wxsCallMethods)) {
  324. return;
  325. }
  326. wxsCallMethods.forEach((callMethod) => {
  327. methods[callMethod] = function (args) {
  328. return this.$vm[callMethod](args);
  329. };
  330. });
  331. }
  332. function selectAllComponents(mpInstance, selector, $refs) {
  333. const components = mpInstance.selectAllComponents(selector);
  334. components.forEach((component) => {
  335. const ref = component.properties.uR;
  336. $refs[ref] = component.$vm || component;
  337. });
  338. }
  339. function initRefs(instance, mpInstance) {
  340. Object.defineProperty(instance, 'refs', {
  341. get() {
  342. const $refs = {};
  343. selectAllComponents(mpInstance, '.r', $refs);
  344. const forComponents = mpInstance.selectAllComponents('.r-i-f');
  345. forComponents.forEach((component) => {
  346. const ref = component.properties.uR;
  347. if (!ref) {
  348. return;
  349. }
  350. if (!$refs[ref]) {
  351. $refs[ref] = [];
  352. }
  353. $refs[ref].push(component.$vm || component);
  354. });
  355. return $refs;
  356. },
  357. });
  358. }
  359. function findVmByVueId(instance, vuePid) {
  360. // 标准 vue3 中 没有 $children,定制了内核
  361. const $children = instance.$children;
  362. // 优先查找直属(反向查找:https://github.com/dcloudio/uni-app/issues/1200)
  363. for (let i = $children.length - 1; i >= 0; i--) {
  364. const childVm = $children[i];
  365. if (childVm.$scope._$vueId === vuePid) {
  366. return childVm;
  367. }
  368. }
  369. // 反向递归查找
  370. let parentVm;
  371. for (let i = $children.length - 1; i >= 0; i--) {
  372. parentVm = findVmByVueId($children[i], vuePid);
  373. if (parentVm) {
  374. return parentVm;
  375. }
  376. }
  377. }
  378. const builtInProps = [
  379. // 百度小程序,快手小程序自定义组件不支持绑定动态事件,动态dataset,故通过props传递事件信息
  380. // event-opts
  381. 'eO',
  382. // 组件 ref
  383. 'uR',
  384. // 组件 ref-in-for
  385. 'uRIF',
  386. // 组件 id
  387. 'uI',
  388. // 组件类型 m: 小程序组件
  389. 'uT',
  390. // 组件 props
  391. 'uP',
  392. // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
  393. 'uS',
  394. ];
  395. function initDefaultProps(options, isBehavior = false) {
  396. const properties = {};
  397. if (!isBehavior) {
  398. // 均不指定类型,避免微信小程序 property received type-uncompatible value 警告
  399. builtInProps.forEach((name) => {
  400. properties[name] = {
  401. type: null,
  402. value: '',
  403. };
  404. });
  405. // 小程序不能直接定义 $slots 的 props,所以通过 vueSlots 转换到 $slots
  406. properties.uS = {
  407. type: null,
  408. value: [],
  409. observer: function (newVal) {
  410. const $slots = Object.create(null);
  411. newVal &&
  412. newVal.forEach((slotName) => {
  413. $slots[slotName] = true;
  414. });
  415. this.setData({
  416. $slots,
  417. });
  418. },
  419. };
  420. }
  421. if (options.behaviors) {
  422. // wx://form-field
  423. if (options.behaviors.includes('qq://form-field')) {
  424. if (!options.properties || !options.properties.name) {
  425. properties.name = {
  426. type: null,
  427. value: '',
  428. };
  429. }
  430. if (!options.properties || !options.properties.value) {
  431. properties.value = {
  432. type: null,
  433. value: '',
  434. };
  435. }
  436. }
  437. }
  438. return properties;
  439. }
  440. function initVirtualHostProps(options) {
  441. const properties = {};
  442. return properties;
  443. }
  444. /**
  445. *
  446. * @param mpComponentOptions
  447. * @param isBehavior
  448. */
  449. function initProps(mpComponentOptions) {
  450. if (!mpComponentOptions.properties) {
  451. mpComponentOptions.properties = {};
  452. }
  453. extend(mpComponentOptions.properties, initDefaultProps(mpComponentOptions), initVirtualHostProps(mpComponentOptions.options));
  454. }
  455. const PROP_TYPES = [String, Number, Boolean, Object, Array, null];
  456. function parsePropType(type, defaultValue) {
  457. // [String]=>String
  458. if (isArray(type) && type.length === 1) {
  459. return type[0];
  460. }
  461. return type;
  462. }
  463. function normalizePropType(type, defaultValue) {
  464. const res = parsePropType(type);
  465. return PROP_TYPES.indexOf(res) !== -1 ? res : null;
  466. }
  467. /**
  468. * 初始化页面 props,方便接收页面参数,类型均为String,默认值均为''
  469. * @param param
  470. * @param rawProps
  471. */
  472. function initPageProps({ properties }, rawProps) {
  473. if (isArray(rawProps)) {
  474. rawProps.forEach((key) => {
  475. properties[key] = {
  476. type: String,
  477. value: '',
  478. };
  479. });
  480. }
  481. else if (isPlainObject(rawProps)) {
  482. Object.keys(rawProps).forEach((key) => {
  483. const opts = rawProps[key];
  484. if (isPlainObject(opts)) {
  485. // title:{type:String,default:''}
  486. let value = opts.default;
  487. if (isFunction(value)) {
  488. value = value();
  489. }
  490. const type = opts.type;
  491. opts.type = normalizePropType(type);
  492. properties[key] = {
  493. type: opts.type,
  494. value,
  495. };
  496. }
  497. else {
  498. // content:String
  499. properties[key] = {
  500. type: normalizePropType(opts),
  501. };
  502. }
  503. });
  504. }
  505. }
  506. function findPropsData(properties, isPage) {
  507. return ((isPage
  508. ? findPagePropsData(properties)
  509. : findComponentPropsData(properties.uP)) || {});
  510. }
  511. function findPagePropsData(properties) {
  512. const propsData = {};
  513. if (isPlainObject(properties)) {
  514. Object.keys(properties).forEach((name) => {
  515. if (builtInProps.indexOf(name) === -1) {
  516. propsData[name] = properties[name];
  517. }
  518. });
  519. }
  520. return propsData;
  521. }
  522. function initFormField(vm) {
  523. // 同步 form-field 的 name,value 值
  524. const vueOptions = vm.$options;
  525. if (isArray(vueOptions.behaviors) &&
  526. vueOptions.behaviors.includes('uni://form-field')) {
  527. vm.$watch('modelValue', () => {
  528. vm.$scope &&
  529. vm.$scope.setData({
  530. name: vm.name,
  531. value: vm.modelValue,
  532. });
  533. }, {
  534. immediate: true,
  535. });
  536. }
  537. }
  538. function initData(_) {
  539. return {};
  540. }
  541. function initPropsObserver(componentOptions) {
  542. const observe = function observe() {
  543. const up = this.properties.uP;
  544. if (!up) {
  545. return;
  546. }
  547. if (this.$vm) {
  548. updateComponentProps(up, this.$vm.$);
  549. }
  550. else if (this.properties.uT === 'm') {
  551. // 小程序组件
  552. updateMiniProgramComponentProperties(up, this);
  553. }
  554. };
  555. {
  556. if (!componentOptions.observers) {
  557. componentOptions.observers = {};
  558. }
  559. componentOptions.observers.uP = 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://', 'qq://'));
  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. function applyOptions(componentOptions, vueOptions) {
  626. componentOptions.data = initData();
  627. componentOptions.behaviors = initBehaviors(vueOptions);
  628. }
  629. function parseComponent(vueOptions, { parse, mocks, isPage, initRelation, handleLink, initLifetimes, }) {
  630. vueOptions = vueOptions.default || vueOptions;
  631. const options = {
  632. multipleSlots: true,
  633. // styleIsolation: 'apply-shared',
  634. addGlobalClass: true,
  635. pureDataPattern: /^uP$/,
  636. };
  637. if (isArray(vueOptions.mixins)) {
  638. vueOptions.mixins.forEach((item) => {
  639. if (isObject(item.options)) {
  640. extend(options, item.options);
  641. }
  642. });
  643. }
  644. if (vueOptions.options) {
  645. extend(options, vueOptions.options);
  646. }
  647. const mpComponentOptions = {
  648. options,
  649. lifetimes: initLifetimes({ mocks, isPage, initRelation, vueOptions }),
  650. pageLifetimes: {
  651. show() {
  652. if (__VUE_PROD_DEVTOOLS__) {
  653. devtoolsComponentAdded(this.$vm.$);
  654. }
  655. this.$vm && this.$vm.$callHook('onPageShow');
  656. },
  657. hide() {
  658. this.$vm && this.$vm.$callHook('onPageHide');
  659. },
  660. resize(size) {
  661. this.$vm && this.$vm.$callHook('onPageResize', size);
  662. },
  663. },
  664. methods: {
  665. __l: handleLink,
  666. },
  667. };
  668. if (__VUE_OPTIONS_API__) {
  669. applyOptions(mpComponentOptions, vueOptions);
  670. }
  671. initProps(mpComponentOptions);
  672. initPropsObserver(mpComponentOptions);
  673. initExtraOptions(mpComponentOptions, vueOptions);
  674. initWxsCallMethods(mpComponentOptions.methods, vueOptions.wxsCallMethods);
  675. if (parse) {
  676. parse(mpComponentOptions, { handleLink });
  677. }
  678. return mpComponentOptions;
  679. }
  680. function initCreateComponent(parseOptions) {
  681. return function createComponent(vueComponentOptions) {
  682. return Component(parseComponent(vueComponentOptions, parseOptions));
  683. };
  684. }
  685. let $createComponentFn;
  686. let $destroyComponentFn;
  687. function getAppVm() {
  688. if (process.env.UNI_MP_PLUGIN) {
  689. return qq.$vm;
  690. }
  691. if (process.env.UNI_SUBPACKAGE) {
  692. return qq.$subpackages[process.env.UNI_SUBPACKAGE].$vm;
  693. }
  694. return getApp().$vm;
  695. }
  696. function $createComponent(initialVNode, options) {
  697. if (!$createComponentFn) {
  698. $createComponentFn = getAppVm().$createComponent;
  699. }
  700. const proxy = $createComponentFn(initialVNode, options);
  701. return getExposeProxy(proxy.$) || proxy;
  702. }
  703. function $destroyComponent(instance) {
  704. if (!$destroyComponentFn) {
  705. $destroyComponentFn = getAppVm().$destroyComponent;
  706. }
  707. return $destroyComponentFn(instance);
  708. }
  709. function parsePage(vueOptions, parseOptions) {
  710. const { parse, mocks, isPage, initRelation, handleLink, initLifetimes } = parseOptions;
  711. const miniProgramPageOptions = parseComponent(vueOptions, {
  712. mocks,
  713. isPage,
  714. initRelation,
  715. handleLink,
  716. initLifetimes,
  717. });
  718. initPageProps(miniProgramPageOptions, (vueOptions.default || vueOptions).props);
  719. const methods = miniProgramPageOptions.methods;
  720. methods.onLoad = function (query) {
  721. this.options = query;
  722. this.$page = {
  723. fullPath: addLeadingSlash(this.route + stringifyQuery(query)),
  724. };
  725. return this.$vm && this.$vm.$callHook(ON_LOAD, query);
  726. };
  727. initHooks(methods, PAGE_INIT_HOOKS);
  728. {
  729. initUnknownHooks(methods, vueOptions);
  730. }
  731. initRuntimeHooks(methods, vueOptions.__runtimeHooks);
  732. initMixinRuntimeHooks(methods);
  733. parse && parse(miniProgramPageOptions, { handleLink });
  734. return miniProgramPageOptions;
  735. }
  736. function initCreatePage(parseOptions) {
  737. return function createPage(vuePageOptions) {
  738. return Component(parsePage(vuePageOptions, parseOptions));
  739. };
  740. }
  741. function initCreatePluginApp(parseAppOptions) {
  742. return function createApp(vm) {
  743. initAppLifecycle(parseApp(vm, parseAppOptions), vm);
  744. if (process.env.UNI_MP_PLUGIN) {
  745. qq.$vm = vm;
  746. }
  747. };
  748. }
  749. const MPPage = Page;
  750. const MPComponent = Component;
  751. function initTriggerEvent(mpInstance) {
  752. const oldTriggerEvent = mpInstance.triggerEvent;
  753. const newTriggerEvent = function (event, ...args) {
  754. return oldTriggerEvent.apply(mpInstance, [customizeEvent(event), ...args]);
  755. };
  756. // 京东小程序triggerEvent为只读属性
  757. try {
  758. mpInstance.triggerEvent = newTriggerEvent;
  759. }
  760. catch (error) {
  761. mpInstance._triggerEvent = newTriggerEvent;
  762. }
  763. }
  764. function initMiniProgramHook(name, options, isComponent) {
  765. const oldHook = options[name];
  766. if (!oldHook) {
  767. options[name] = function () {
  768. initTriggerEvent(this);
  769. };
  770. }
  771. else {
  772. options[name] = function (...args) {
  773. initTriggerEvent(this);
  774. return oldHook.apply(this, args);
  775. };
  776. }
  777. }
  778. Page = function (options) {
  779. initMiniProgramHook(ON_LOAD, options);
  780. return MPPage(options);
  781. };
  782. Component = function (options) {
  783. initMiniProgramHook('created', options);
  784. // 小程序组件
  785. const isVueComponent = options.properties && options.properties.uP;
  786. if (!isVueComponent) {
  787. initProps(options);
  788. initPropsObserver(options);
  789. }
  790. return MPComponent(options);
  791. };
  792. // @ts-ignore
  793. function initLifetimes({ mocks, isPage, initRelation, vueOptions, }) {
  794. return {
  795. attached() {
  796. let properties = this.properties;
  797. initVueIds(properties.uI, this);
  798. const relationOptions = {
  799. vuePid: this._$vuePid,
  800. };
  801. // 处理父子关系
  802. initRelation(this, relationOptions);
  803. // 初始化 vue 实例
  804. const mpInstance = this;
  805. const isMiniProgramPage = isPage(mpInstance);
  806. let propsData = properties;
  807. this.$vm = $createComponent({
  808. type: vueOptions,
  809. props: findPropsData(propsData, isMiniProgramPage),
  810. }, {
  811. mpType: isMiniProgramPage ? 'page' : 'component',
  812. mpInstance,
  813. slots: properties.uS || {},
  814. parentComponent: relationOptions.parent && relationOptions.parent.$,
  815. onBeforeSetup(instance, options) {
  816. initRefs(instance, mpInstance);
  817. initMocks(instance, mpInstance, mocks);
  818. initComponentInstance(instance, options);
  819. },
  820. });
  821. if (!isMiniProgramPage) {
  822. initFormField(this.$vm);
  823. }
  824. },
  825. ready() {
  826. // 当组件 props 默认值为 true,初始化时传入 false 会导致 created,ready 触发, 但 attached 不触发
  827. // https://developers.weixin.qq.com/community/develop/doc/00066ae2844cc0f8eb883e2a557800
  828. if (this.$vm) {
  829. {
  830. this.$vm.$callHook('mounted');
  831. this.$vm.$callHook(ON_READY);
  832. }
  833. }
  834. },
  835. detached() {
  836. if (this.$vm) {
  837. pruneComponentPropsCache(this.$vm.$.uid);
  838. $destroyComponent(this.$vm);
  839. }
  840. },
  841. };
  842. }
  843. const mocks = ['__route__', '__wxExparserNodeId__', '__wxWebviewId__'];
  844. function isPage(mpInstance) {
  845. return !!mpInstance.route;
  846. }
  847. function initRelation(mpInstance, detail) {
  848. mpInstance.triggerEvent('__l', detail);
  849. }
  850. function handleLink(event) {
  851. // detail 是微信,value 是百度(dipatch)
  852. const detail = (event.detail ||
  853. event.value);
  854. const vuePid = detail.vuePid;
  855. let parentVm;
  856. if (vuePid) {
  857. parentVm = findVmByVueId(this.$vm, vuePid);
  858. }
  859. if (!parentVm) {
  860. parentVm = this.$vm;
  861. }
  862. detail.parent = parentVm;
  863. }
  864. var parseOptions = /*#__PURE__*/Object.freeze({
  865. __proto__: null,
  866. handleLink: handleLink,
  867. initLifetimes: initLifetimes,
  868. initRelation: initRelation,
  869. isPage: isPage,
  870. mocks: mocks
  871. });
  872. const createApp = initCreateApp();
  873. const createPage = initCreatePage(parseOptions);
  874. const createComponent = initCreateComponent(parseOptions);
  875. const createPluginApp = initCreatePluginApp();
  876. const createSubpackageApp = initCreateSubpackageApp();
  877. qq.EventChannel = EventChannel;
  878. qq.createApp = global.createApp = createApp;
  879. qq.createPage = createPage;
  880. qq.createComponent = createComponent;
  881. qq.createSubpackageApp = global.createSubpackageApp =
  882. createSubpackageApp;
  883. export { createApp, createComponent, createPage, createPluginApp, createSubpackageApp };