@tarojs/plugin-framework-react 3.7.0-alpha.2 → 3.7.0-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/runtime.js CHANGED
@@ -1,5 +1,5 @@
1
- import { EMPTY_OBJ, isFunction, isArray, isWebPlatform, hooks, ensure } from '@tarojs/shared';
2
- import { Current, getPageInstance, injectPageInstance, incrementId, document, safeExecute, eventHandler, addLeadingSlash, removePageInstance } from '@tarojs/runtime';
1
+ import { EMPTY_OBJ, isFunction, isArray, isWebPlatform, hooks, ensure, isUndefined } from '@tarojs/shared';
2
+ import { Current, getPageInstance, injectPageInstance, incrementId, document, getPath, window, CONTEXT_ACTIONS, safeExecute, removePageInstance, ON_READY, requestAnimationFrame, eventCenter, getOnReadyEventKey, ON_SHOW, getOnShowEventKey, ON_HIDE, getOnHideEventKey, eventHandler, addLeadingSlash } from '@tarojs/runtime';
3
3
 
4
4
  const reactMeta = {
5
5
  PageContext: EMPTY_OBJ,
@@ -473,7 +473,9 @@ function createReactApp(App, react, dom, config) {
473
473
  const getNativeCompId = incrementId();
474
474
  let h;
475
475
  let ReactDOM;
476
- function initNativeComponentEntry(R, ReactDOM) {
476
+ let nativeComponentApp;
477
+ function initNativeComponentEntry(params) {
478
+ const { R, ReactDOM, cb, isDefaultEntryDom = true } = params;
477
479
  class NativeComponentWrapper extends R.Component {
478
480
  constructor() {
479
481
  super(...arguments);
@@ -488,7 +490,8 @@ function initNativeComponentEntry(R, ReactDOM) {
488
490
  }
489
491
  render() {
490
492
  return (h('root', {
491
- ref: this.root
493
+ ref: this.root,
494
+ id: this.props.compId
492
495
  }, this.props.renderComponent(this.ctx)));
493
496
  }
494
497
  }
@@ -500,9 +503,15 @@ function initNativeComponentEntry(R, ReactDOM) {
500
503
  };
501
504
  }
502
505
  componentDidMount() {
503
- Current.app = this;
506
+ if (isDefaultEntryDom) {
507
+ Current.app = this;
508
+ }
509
+ else {
510
+ nativeComponentApp = this;
511
+ }
512
+ cb && cb();
504
513
  }
505
- mount(Component, compId, getCtx) {
514
+ mount(Component, compId, getCtx, cb) {
506
515
  const isReactComponent = isClassComponent(R, Component);
507
516
  const inject = (node) => node && injectPageInstance(node, compId);
508
517
  const refs = isReactComponent ? { ref: inject } : {
@@ -516,6 +525,7 @@ function initNativeComponentEntry(R, ReactDOM) {
516
525
  compId,
517
526
  element: h(NativeComponentWrapper, {
518
527
  key: compId,
528
+ compId,
519
529
  getCtx,
520
530
  renderComponent(ctx) {
521
531
  return h(reactMeta.PageContext.Provider, { value: compId }, h(Component, Object.assign(Object.assign(Object.assign({}, (ctx.data || (ctx.data = {})).props), refs), { $scope: ctx })));
@@ -524,9 +534,9 @@ function initNativeComponentEntry(R, ReactDOM) {
524
534
  };
525
535
  this.setState({
526
536
  components: [...this.state.components, item]
527
- });
537
+ }, () => cb && cb());
528
538
  }
529
- unmount(compId) {
539
+ unmount(compId, cb) {
530
540
  const components = this.state.components;
531
541
  const index = components.findIndex(item => item.compId === compId);
532
542
  const next = [...components.slice(0, index), ...components.slice(index + 1)];
@@ -534,6 +544,7 @@ function initNativeComponentEntry(R, ReactDOM) {
534
544
  components: next
535
545
  }, () => {
536
546
  removePageInstance(compId);
547
+ cb && cb();
537
548
  });
538
549
  }
539
550
  render() {
@@ -542,15 +553,187 @@ function initNativeComponentEntry(R, ReactDOM) {
542
553
  }
543
554
  }
544
555
  setReconciler(ReactDOM);
545
- const app = document.getElementById('app');
556
+ let app = document.getElementById('app');
557
+ if (!isDefaultEntryDom && !nativeComponentApp) {
558
+ // create
559
+ const nativeApp = document.createElement('nativeComponent');
560
+ // insert
561
+ app.appendChild(nativeApp);
562
+ app = nativeApp;
563
+ }
546
564
  ReactDOM.render(h(Entry, {}), app);
547
565
  }
566
+ function createNativePageConfig(Component, pageName, data, react, reactdom, pageConfig) {
567
+ reactMeta.R = react;
568
+ h = react.createElement;
569
+ ReactDOM = reactdom;
570
+ setReconciler(ReactDOM);
571
+ const [ONLOAD, ONUNLOAD, ONREADY, ONSHOW, ONHIDE, LIFECYCLES, SIDE_EFFECT_LIFECYCLES] = hooks.call('getMiniLifecycleImpl').page;
572
+ let unmounting = false;
573
+ let prepareMountList = [];
574
+ let pageElement = null;
575
+ let loadResolver;
576
+ let hasLoaded;
577
+ const id = pageName !== null && pageName !== void 0 ? pageName : `taro_page_${getNativeCompId()}`;
578
+ function setCurrentRouter(page) {
579
+ const router = page.route || page.__route__ || page.$taroPath;
580
+ Current.router = {
581
+ params: page.$taroParams,
582
+ path: addLeadingSlash(router),
583
+ $taroPath: page.$taroPath,
584
+ onReady: getOnReadyEventKey(id),
585
+ onShow: getOnShowEventKey(id),
586
+ onHide: getOnHideEventKey(id)
587
+ };
588
+ if (!isUndefined(page.exitState)) {
589
+ Current.router.exitState = page.exitState;
590
+ }
591
+ }
592
+ const pageObj = {
593
+ options: pageConfig,
594
+ [ONLOAD](options = {}, cb) {
595
+ hasLoaded = new Promise(resolve => { loadResolver = resolve; });
596
+ Current.page = this;
597
+ this.config = pageConfig || {};
598
+ // this.$taroPath 是页面唯一标识
599
+ const uniqueOptions = Object.assign({}, options, { $taroTimestamp: Date.now() });
600
+ const $taroPath = this.$taroPath = getPath(id, uniqueOptions);
601
+ // this.$taroParams 作为暴露给开发者的页面参数对象,可以被随意修改
602
+ if (this.$taroParams == null) {
603
+ this.$taroParams = uniqueOptions;
604
+ }
605
+ setCurrentRouter(this);
606
+ window.trigger(CONTEXT_ACTIONS.INIT, $taroPath);
607
+ const mountCallback = () => {
608
+ pageElement = document.getElementById($taroPath);
609
+ ensure(pageElement !== null, '没有找到页面实例。');
610
+ safeExecute($taroPath, ONLOAD, this.$taroParams);
611
+ loadResolver();
612
+ pageElement.ctx = this;
613
+ pageElement.performUpdate(true, cb);
614
+ };
615
+ const mount = () => {
616
+ if (!Current.app) {
617
+ initNativeComponentEntry({
618
+ R: react,
619
+ ReactDOM,
620
+ cb: () => {
621
+ Current.app.mount(Component, $taroPath, () => this, mountCallback);
622
+ }
623
+ });
624
+ }
625
+ else {
626
+ Current.app.mount(Component, $taroPath, () => this, mountCallback);
627
+ }
628
+ };
629
+ if (unmounting) {
630
+ prepareMountList.push(mount);
631
+ }
632
+ else {
633
+ mount();
634
+ }
635
+ },
636
+ [ONUNLOAD]() {
637
+ const $taroPath = this.$taroPath;
638
+ // 销毁当前页面的上下文信息
639
+ window.trigger(CONTEXT_ACTIONS.DESTORY, $taroPath);
640
+ // 触发onUnload生命周期
641
+ safeExecute($taroPath, ONUNLOAD);
642
+ resetCurrent();
643
+ unmounting = true;
644
+ Current.app.unmount($taroPath, () => {
645
+ unmounting = false;
646
+ removePageInstance($taroPath);
647
+ if (pageElement) {
648
+ pageElement.ctx = null;
649
+ pageElement = null;
650
+ }
651
+ if (prepareMountList.length) {
652
+ prepareMountList.forEach(fn => fn());
653
+ prepareMountList = [];
654
+ }
655
+ });
656
+ },
657
+ [ONREADY]() {
658
+ hasLoaded.then(() => {
659
+ // 触发生命周期
660
+ safeExecute(this.$taroPath, ON_READY);
661
+ // 通过事件触发子组件的生命周期
662
+ requestAnimationFrame(() => eventCenter.trigger(getOnReadyEventKey(id)));
663
+ this.onReady.called = true;
664
+ });
665
+ },
666
+ [ONSHOW](options = {}) {
667
+ hasLoaded.then(() => {
668
+ // 设置 Current 的 page 和 router
669
+ Current.page = this;
670
+ setCurrentRouter(this);
671
+ // 恢复上下文信息
672
+ window.trigger(CONTEXT_ACTIONS.RECOVER, this.$taroPath);
673
+ // 触发生命周期
674
+ safeExecute(this.$taroPath, ON_SHOW, options);
675
+ // 通过事件触发子组件的生命周期
676
+ requestAnimationFrame(() => eventCenter.trigger(getOnShowEventKey(id)));
677
+ });
678
+ },
679
+ [ONHIDE]() {
680
+ // 缓存当前页面上下文信息
681
+ window.trigger(CONTEXT_ACTIONS.RESTORE, this.$taroPath);
682
+ // 设置 Current 的 page 和 router
683
+ if (Current.page === this) {
684
+ Current.page = null;
685
+ Current.router = null;
686
+ }
687
+ // 触发生命周期
688
+ safeExecute(this.$taroPath, ON_HIDE);
689
+ // 通过事件触发子组件的生命周期
690
+ eventCenter.trigger(getOnHideEventKey(id));
691
+ },
692
+ };
693
+ function resetCurrent() {
694
+ // 小程序插件页面卸载之后返回到宿主页面时,需重置Current页面和路由。否则引发插件组件二次加载异常 fix:#11991
695
+ Current.page = null;
696
+ Current.router = null;
697
+ }
698
+ LIFECYCLES.forEach((lifecycle) => {
699
+ pageObj[lifecycle] = function () {
700
+ return safeExecute(this.$taroPath, lifecycle, ...arguments);
701
+ };
702
+ });
703
+ // onShareAppMessage 和 onShareTimeline 一样,会影响小程序右上方按钮的选项,因此不能默认注册。
704
+ SIDE_EFFECT_LIFECYCLES.forEach(lifecycle => {
705
+ var _a;
706
+ if (Component[lifecycle] ||
707
+ ((_a = Component.prototype) === null || _a === void 0 ? void 0 : _a[lifecycle]) ||
708
+ Component[lifecycle.replace(/^on/, 'enable')]) {
709
+ pageObj[lifecycle] = function (...args) {
710
+ var _a;
711
+ const target = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.target;
712
+ if (target === null || target === void 0 ? void 0 : target.id) {
713
+ const id = target.id;
714
+ const element = document.getElementById(id);
715
+ if (element) {
716
+ target.dataset = element.dataset;
717
+ }
718
+ }
719
+ return safeExecute(this.$taroPath, lifecycle, ...args);
720
+ };
721
+ }
722
+ });
723
+ pageObj.eh = eventHandler;
724
+ if (!isUndefined(data)) {
725
+ pageObj.data = data;
726
+ }
727
+ hooks.call('modifyPageObject', pageObj);
728
+ return pageObj;
729
+ }
548
730
  function createNativeComponentConfig(Component, react, reactdom, componentConfig) {
549
731
  var _a, _b;
550
732
  reactMeta.R = react;
551
733
  h = react.createElement;
552
734
  ReactDOM = reactdom;
553
735
  setReconciler(ReactDOM);
736
+ const { isNewBlended } = componentConfig;
554
737
  const componentObj = {
555
738
  options: componentConfig,
556
739
  properties: {
@@ -564,22 +747,37 @@ function createNativeComponentConfig(Component, react, reactdom, componentConfig
564
747
  }
565
748
  },
566
749
  created() {
567
- if (!Current.app) {
568
- initNativeComponentEntry(react, ReactDOM);
750
+ const app = (isNewBlended ? nativeComponentApp : Current.app);
751
+ if (!app) {
752
+ initNativeComponentEntry({
753
+ R: react,
754
+ ReactDOM,
755
+ isDefaultEntryDom: !isNewBlended
756
+ });
569
757
  }
570
758
  },
571
759
  attached() {
572
760
  const compId = this.compId = getNativeCompId();
573
761
  setCurrent(compId);
574
762
  this.config = componentConfig;
575
- Current.app.mount(Component, compId, () => this);
763
+ const app = (isNewBlended ? nativeComponentApp : Current.app);
764
+ app.mount(Component, compId, () => this, () => {
765
+ const instance = getPageInstance(compId);
766
+ if (instance && instance.node) {
767
+ const el = document.getElementById(instance.node.uid);
768
+ if (el) {
769
+ el.ctx = this;
770
+ }
771
+ }
772
+ });
576
773
  },
577
774
  ready() {
578
775
  safeExecute(this.compId, 'onReady');
579
776
  },
580
777
  detached() {
581
778
  resetCurrent();
582
- Current.app.unmount(this.compId);
779
+ const app = (isNewBlended ? nativeComponentApp : Current.app);
780
+ app.unmount(this.compId);
583
781
  },
584
782
  pageLifetimes: {
585
783
  show(options) {
@@ -604,37 +802,6 @@ function createNativeComponentConfig(Component, react, reactdom, componentConfig
604
802
  Current.page = null;
605
803
  Current.router = null;
606
804
  }
607
- function setCurrent(compId) {
608
- const pages = getCurrentPages();
609
- const currentPage = pages[pages.length - 1];
610
- if (Current.page === currentPage)
611
- return;
612
- Current.page = currentPage;
613
- const route = currentPage.route || currentPage.__route__;
614
- const router = {
615
- params: currentPage.options || {},
616
- path: addLeadingSlash(route),
617
- $taroPath: compId,
618
- onReady: '',
619
- onHide: '',
620
- onShow: ''
621
- };
622
- Current.router = router;
623
- if (!currentPage.options) {
624
- // 例如在微信小程序中,页面 options 的设置时机比组件 attached 慢
625
- Object.defineProperty(currentPage, 'options', {
626
- enumerable: true,
627
- configurable: true,
628
- get() {
629
- return this._optionsValue;
630
- },
631
- set(value) {
632
- router.params = value;
633
- this._optionsValue = value;
634
- }
635
- });
636
- }
637
- }
638
805
  // onShareAppMessage 和 onShareTimeline 一样,会影响小程序右上方按钮的选项,因此不能默认注册。
639
806
  if (Component.onShareAppMessage ||
640
807
  ((_a = Component.prototype) === null || _a === void 0 ? void 0 : _a.onShareAppMessage) ||
@@ -660,13 +827,46 @@ function createNativeComponentConfig(Component, react, reactdom, componentConfig
660
827
  }
661
828
  return componentObj;
662
829
  }
830
+ function setCurrent(compId) {
831
+ if (!getCurrentPages || typeof getCurrentPages !== 'function')
832
+ return;
833
+ const pages = getCurrentPages();
834
+ const currentPage = pages[pages.length - 1];
835
+ if (Current.page === currentPage)
836
+ return;
837
+ Current.page = currentPage;
838
+ const route = currentPage.route || currentPage.__route__;
839
+ const router = {
840
+ params: currentPage.options || {},
841
+ path: addLeadingSlash(route),
842
+ $taroPath: compId,
843
+ onReady: '',
844
+ onHide: '',
845
+ onShow: ''
846
+ };
847
+ Current.router = router;
848
+ if (!currentPage.options) {
849
+ // 例如在微信小程序中,页面 options 的设置时机比组件 attached 慢
850
+ Object.defineProperty(currentPage, 'options', {
851
+ enumerable: true,
852
+ configurable: true,
853
+ get() {
854
+ return this._optionsValue;
855
+ },
856
+ set(value) {
857
+ router.params = value;
858
+ this._optionsValue = value;
859
+ }
860
+ });
861
+ }
862
+ }
663
863
 
664
864
  hooks.tap('initNativeApi', function (taro) {
665
865
  for (const hook in taroHooks) {
666
866
  taro[hook] = taroHooks[hook];
667
867
  }
668
868
  });
669
- if (__TARO_FRAMEWORK__ === 'preact') {
869
+ if (__TARO_FRAMEWORK__ === 'preact' && process.env.TARO_PLATFORM === 'mini') {
670
870
  const options = require('preact').options;
671
871
  const oldVNodeHook = options.vnode;
672
872
  const oldDiffedHook = options.diffed;
@@ -729,5 +929,5 @@ if (__TARO_FRAMEWORK__ === 'preact') {
729
929
  // })
730
930
  }
731
931
 
732
- export { connectReactPage, createNativeComponentConfig, createReactApp, setReconciler, useAddToFavorites, useDidHide, useDidShow, useError, useLaunch, useLoad, useOptionMenuClick, usePageNotFound, usePageScroll, usePullDownRefresh, usePullIntercept, useReachBottom, useReady, useResize, useRouter, useSaveExitState, useScope, useShareAppMessage, useShareTimeline, useTabItemTap, useTitleClick, useUnhandledRejection, useUnload };
932
+ export { connectReactPage, createNativeComponentConfig, createNativePageConfig, createReactApp, setReconciler, useAddToFavorites, useDidHide, useDidShow, useError, useLaunch, useLoad, useOptionMenuClick, usePageNotFound, usePageScroll, usePullDownRefresh, usePullIntercept, useReachBottom, useReady, useResize, useRouter, useSaveExitState, useScope, useShareAppMessage, useShareTimeline, useTabItemTap, useTitleClick, useUnhandledRejection, useUnload };
733
933
  //# sourceMappingURL=runtime.js.map