public performUpdate()

in packages/miniapp-runtime/src/dom/root.ts [82:184]


  public performUpdate(initRender = false, prerender?: Func) {
    this.pendingUpdate = true;

    const ctx = this.ctx!;

    setTimeout(() => {
      perf.start(SET_DATA);
      const data: Record<string, UpdatePayloadValue | ReturnType<HydratedData>> = Object.create(null);
      const resetPaths = new Set<string>(
        initRender
          ? ['root.cn.[0]', 'root.cn[0]']
          : [],
      );

      while (this.updatePayloads.length > 0) {
        const { path, value } = this.updatePayloads.shift()!;
        if (path.endsWith(Shortcuts.Childnodes)) {
          resetPaths.add(path);
        }
        data[path] = value;
      }

      for (const path in data) {
        resetPaths.forEach(p => {
          // 已经重置了数组,就不需要分别再设置了
          if (path.includes(p) && path !== p) {
            delete data[path];
          }
        });

        const value = data[path];
        if (isFunction(value)) {
          data[path] = value();
        }
      }

      // 预渲染
      if (isFunction(prerender)) return prerender(data);

      // 正常渲染
      this.pendingUpdate = false;
      let normalUpdate = {};
      const customWrapperMap: Map<Record<any, any>, Record<string, any>> = new Map();

      if (initRender) {
        // 初次渲染,使用页面级别的 setData
        normalUpdate = data;
      } else {
        // 更新渲染,区分 CustomWrapper 与页面级别的 setData
        for (const p in data) {
          const dataPathArr = p.split('.');
          const found = findCustomWrapper(this, dataPathArr);
          if (found) {
            // 此项数据使用 CustomWrapper 去更新
            const { customWrapper, splitedPath } = found;
            // 合并同一个 customWrapper 的相关更新到一次 setData 中
            customWrapperMap.set(customWrapper, {
              ...(customWrapperMap.get(customWrapper) || {}),
              [`i.${splitedPath}`]: data[p],
            });
          } else {
            // 此项数据使用页面去更新
            normalUpdate[p] = data[p];
          }
        }
      }

      const customWrpperCount = customWrapperMap.size;
      const isNeedNormalUpdate = Object.keys(normalUpdate).length > 0;
      const updateArrLen = customWrpperCount + (isNeedNormalUpdate ? 1 : 0);
      let executeTime = 0;

      const cb = () => {
        if (++executeTime === updateArrLen) {
          perf.stop(SET_DATA);
          this.flushUpdateCallback();
          initRender && perf.stop(PAGE_INIT);
        }
      };

      // custom-wrapper setData
      if (customWrpperCount) {
        customWrapperMap.forEach((data, ctx) => {
          if (process.env.NODE_ENV !== 'production' && options.debug) {
            // eslint-disable-next-line no-console
            console.log('custom wrapper setData: ', data);
          }
          hooks.call('modifySetDataPayload', data, ctx);
          ctx.setData(data, cb);
        });
      }

      // page setData
      if (isNeedNormalUpdate) {
        if (process.env.NODE_ENV !== 'production' && options.debug) {
          // eslint-disable-next-line no-console
          console.log('page setData:', normalUpdate);
        }
        hooks.call('modifySetDataPayload', data, ctx);
        ctx.setData(normalUpdate, cb);
      }
    }, 0);
  }