@ray-core/runtime
Version:
Ray 是一个全新的基于 React 的小程序开发框架
251 lines (250 loc) • 11.1 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
import { RuntimeOptions } from '@ray-core/framework-shared';
import merge from 'lodash-es/merge';
import get from 'lodash-es/get';
import cloneDeep from 'lodash-es/cloneDeep';
import VNode from './VNode';
import nativeEffector from './nativeEffect';
import { unstable_batchedUpdates } from './index';
import { SLOT_PLACEHOLDER } from './constants';
import { gStore } from './gStore';
import { createCallbackProxy } from './SyntheticEvent/createCallbackProxy';
var Container = /** @class */ (function () {
function Container(context, rootKey) {
if (rootKey === void 0) { rootKey = 'root'; }
this.updateQueue = [];
this._slot = { idsCache: [], node: undefined };
this.pageInitialized = false;
this.context = context;
this.root = new VNode({
type: 'root',
container: this,
});
this.root.mounted = true;
this.rootKey = rootKey;
}
Container.prototype.requestUpdate = function (update) {
this.updateQueue.push(update);
};
Container.prototype.normalizeUpdatePath = function (paths) {
return __spreadArray([this.rootKey], __read(paths), false).join('.');
};
Container.prototype.handlePayload = function (pathPrefix) {
var _this = this;
return this.updateQueue.reduce(function (acc, update) {
if (update.node.isDeleted()) {
return acc;
}
var _path = update.path;
if (update.type === 'splice') {
acc[_this.normalizeUpdatePath(__spreadArray(__spreadArray(__spreadArray([], __read(pathPrefix), false), __read(_path), false), ['nodes', update.id.toString()], false))] = update.raw || null;
if (update.children) {
var path = __spreadArray(__spreadArray(__spreadArray([], __read(pathPrefix), false), __read(_path), false), ['children'], false);
acc[_this.normalizeUpdatePath(path)] = (update.children || []).map(function (c) { return c.id; });
}
}
else {
acc[_this.normalizeUpdatePath(__spreadArray(__spreadArray(__spreadArray([], __read(pathPrefix), false), __read(_path), false), [update.name], false))] = update.value;
}
return acc;
}, {});
};
Container.prototype.applyUpdate = function (appContainer) {
if (this.stopUpdate) {
return;
}
if (!appContainer) {
if (this.updateQueue.length === 0) {
return;
}
}
if (appContainer && appContainer.updateQueue.length === 0 && this.updateQueue.length === 0) {
return;
}
var startTime = new Date().getTime();
var realParentPath = [];
var appPayload;
var pagePayload;
// 从 app.js 中获取 ui 数据
// ray 构建的组件 不需要从 app.js 获取 ui 数据
// modal UI 仍然由各个页面控制
if (appContainer) {
appPayload = appContainer.handlePayload();
var slotInfo = appContainer.getPageSlotParentInfo();
// 当app.js 中 未渲染页面时 slot 不存在
if (slotInfo) {
var slotIndexAtParentChildren = slotInfo.slotIndexAtParentChildren;
realParentPath = slotInfo.parentPath;
pagePayload = this.handlePayload(realParentPath);
var realParentChildrenPathStr = __spreadArray(__spreadArray([this.rootKey], __read(realParentPath), false), ['children'], false).join('.');
var childrenOfPage = this.root.children.map(function (c) { return c.id; });
if (!this.pageInitialized) {
this.pageInitialized = true;
// 页面初始化的时候,从app.js中获取全量的 ui 数据
appPayload = cloneDeep(appContainer.context.getData());
}
var parentChildrenOfApp = get(appPayload, realParentChildrenPathStr);
if (parentChildrenOfApp) {
if (this.root.children.length) {
parentChildrenOfApp.splice.apply(parentChildrenOfApp, __spreadArray([slotIndexAtParentChildren, 1], __read(childrenOfPage), false));
}
else {
parentChildrenOfApp.splice(slotIndexAtParentChildren, 1);
}
delete pagePayload[realParentChildrenPathStr];
appPayload[realParentChildrenPathStr] = parentChildrenOfApp;
}
}
}
else {
pagePayload = this.handlePayload(realParentPath);
}
// fullPayload = appPayload + pagePayload
if (RuntimeOptions.get('debug')) {
console.log('>>>>>>>> applyUpdate appPayload', appPayload);
console.log('>>>>>>>> applyUpdate pagePayload', pagePayload);
}
var fullPayload = merge({}, appPayload, pagePayload);
if (RuntimeOptions.get('debug')) {
console.log('>>>>>>>> applyUpdate fullPayload ', this.context.route, fullPayload);
}
this.context.setData(fullPayload, function () {
nativeEffector.run();
/* istanbul ignore next */
if (RuntimeOptions.get('debug')) {
console.log("setData => \u56DE\u8C03\u65F6\u95F4\uFF1A".concat(new Date().getTime() - startTime, "ms"), fullPayload);
}
});
this.updateQueue = [];
};
Container.prototype.clearUpdate = function () {
this.stopUpdate = true;
};
Container.prototype.createCallback = function (id, propKey, node, fn) {
var proxyHandle = createCallbackProxy(propKey, node, fn);
function cbOrEventHandler() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return unstable_batchedUpdates(function (args) {
return proxyHandle.apply(void 0, __spreadArray([], __read(args), false));
}, args);
}
cbOrEventHandler.__original = fn;
// 微信端:除input事件需要挂在实例上外,其他事件都可以挂在原型上
if (/^(onInput|bindinput)$/.test(propKey)) {
this.context[id] = cbOrEventHandler;
}
gStore.setCallback(id, cbOrEventHandler);
};
Container.prototype.removeCallback = function (name) {
gStore.unsetCallback(name);
delete this.context[name];
};
Container.prototype.appendChild = function (child) {
this.root.appendChild(child);
};
Container.prototype.removeChild = function (child) {
this.root.removeChild(child);
};
Container.prototype.insertBefore = function (child, beforeChild) {
this.root.insertBefore(child, beforeChild);
};
Container.prototype.replaceSlot = function (parent, child, index) {
var _a, _b;
if ((_a = child.text) === null || _a === void 0 ? void 0 : _a.startsWith(SLOT_PLACEHOLDER)) {
var slotChildren = ((_b = this._slot.node) === null || _b === void 0 ? void 0 : _b.children) || []; // 页面中Ray构建的原生自定义组件根节点 // 子节点
slotChildren = slotChildren.map(function (item) { return ((item.parent = parent), item); });
var curChildren = parent.children;
if (typeof index === 'number') {
// 首次插入中间位置
curChildren.splice.apply(curChildren, __spreadArray([index, 0], __read(slotChildren), false));
}
else {
var idsCache = this._slot.idsCache;
if (idsCache.length === 0) {
curChildren.push.apply(curChildren, __spreadArray([], __read(slotChildren), false)); // 首次追加到尾部
}
else {
// 更新
var start = -1;
for (var i = 0; i < curChildren.length; i++) {
var item = curChildren[i];
if (~idsCache.indexOf(item.id)) {
curChildren.splice(i, 1);
if (start < 0)
start = i;
i--;
}
}
curChildren.splice.apply(curChildren, __spreadArray([start, 0], __read(slotChildren), false));
}
}
this._slot.idsCache = slotChildren.map(function (item) { return item.id; });
parent.children = curChildren;
return slotChildren;
}
};
Container.prototype.removeSlot = function (parent, child) {
var _a;
if (!((_a = child.text) === null || _a === void 0 ? void 0 : _a.startsWith(SLOT_PLACEHOLDER))) {
return;
}
if (this._slot.node) {
this._slot.node.children.forEach(function (slot) {
parent.children = parent.children.filter(function (child) {
return child.id !== slot.id;
});
});
this._slot.idsCache = [];
this._slot.node = undefined;
}
};
Container.prototype.copyVNode = function (node, option) {
var _this = this;
var fn = function (node, opts) {
var o = Object.create(Object.getPrototypeOf(node), Object.getOwnPropertyDescriptors(node));
o.children = o.children.map(function (c) { return fn(c, { parent: o, container: _this }); });
return Object.assign(o, opts);
};
return fn(node, __assign(__assign({}, option), { container: this }));
};
return Container;
}());
export default Container;