vasille-jsx
Version:
The first Developer eXperience Orientated front-end framework (JSX components)
94 lines (93 loc) • 2.84 kB
JavaScript
import { Fragment, App, reportError, IValue, Reference } from "vasille";
function create(node, renderer, props, callback, slot, name) {
if (!node) {
throw new Error("Vasille: Component context is missing");
}
const frag = new Fragment(props, node.runner, name);
if (slot) {
props.slot = slot;
}
node.create(frag);
try {
const result = renderer(frag, props);
if (result !== undefined && callback) {
callback(result);
}
}
catch (e) {
reportError(e);
}
}
function fieldError(key) {
return new Error([
`Vasille: Field ${key} has a reactive value, which is not allowed in model.`,
"Use bridge.stored() to disable the reactivity of value,",
"or hybridView properties parameter which accepts reactive values.",
].join(" "));
}
function getProp(target, p, isModel) {
if (isModel) {
const value = target[p];
if (value instanceof IValue) {
throw fieldError(String(p));
}
return value;
}
else {
const value = target[p];
if (value instanceof IValue) {
return value;
}
return (target[p] = new Reference(target[p]));
}
}
export function mvvmView(renderer, name) {
return function (props, node, slot) {
create(node, renderer, new Proxy(props, {
get(target, p) {
return getProp(target, p);
},
}), props.callback, slot, name);
};
}
export function mvcView(renderer, name) {
return function (props, node, slot) {
for (const key in props) {
if (props[key] instanceof IValue) {
throw fieldError(key);
}
}
create(node, renderer, props, props.callback, slot, name);
};
}
export function hybridView(renderer, modelProps, name) {
if (modelProps.length === 0) {
return mvvmView(renderer, name);
}
else if (modelProps.length === 1) {
const key = modelProps[0];
return function (props, node, slot) {
create(node, renderer, new Proxy(props, {
get(target, p) {
return getProp(target, p, key === p);
},
}), props.callback, slot, name);
};
}
const modelPropsSet = new Set(modelProps);
return function (props, node, slot) {
create(node, renderer, new Proxy(props, {
get(target, p) {
return getProp(target, p, modelPropsSet.has(p));
},
}), props.callback, slot, name);
};
}
export function mount(tag, view, runner, $) {
const root = new App(tag, runner, {});
const frag = new Fragment({}, runner, ":app-root");
root.create(frag, function () {
view($, frag);
});
return root;
}