@form-create/core
Version:
FormCreate低代码表单渲染引擎,可以通过 JSON 生成具有动态渲染、数据收集、验证和提交功能的低代码表单。支持6个UI框架,适配移动端,并且支持生成任何 Vue 组件。
179 lines (170 loc) • 7.08 kB
JavaScript
import extend from '@form-create/utils/lib/extend';
import toCase from '@form-create/utils/lib/tocase';
import BaseParser from '../factory/parser';
import {$del} from '@form-create/utils/lib/modify';
import is, {hasProperty} from '@form-create/utils/lib/type';
import {invoke} from '../frame/util';
const noneKey = ['field', 'value', 'vm', 'template', 'name', 'config', 'control', 'inject', 'sync', 'payload', 'optionsTo', 'update', 'component', 'cache'];
export default function useContext(Handler) {
extend(Handler.prototype, {
getCtx(id) {
return this.getFieldCtx(id) || this.getNameCtx(id)[0] || this.ctxs[id];
},
getCtxs(id) {
return this.fieldCtx[id] || this.nameCtx[id] || (this.ctxs[id] ? [this.ctxs[id]] : []);
},
setIdCtx(ctx, key, type) {
const field = `${type}Ctx`;
if (!this[field][key]) {
this[field][key] = [ctx];
} else {
this[field][key].push(ctx);
}
},
rmIdCtx(ctx, key, type) {
const field = `${type}Ctx`;
const lst = this[field][key];
if (!lst) return false;
const flag = lst.splice(lst.indexOf(ctx) >>> 0, 1).length > 0;
if (!lst.length) {
delete this[field][key];
}
return flag;
},
getFieldCtx(field) {
return (this.fieldCtx[field] || [])[0];
},
getNameCtx(name) {
return this.nameCtx[name] || [];
},
setCtx(ctx) {
let {id, field, name, rule} = ctx;
this.ctxs[id] = ctx;
name && this.setIdCtx(ctx, name, 'name');
if (!ctx.input) return;
this.setIdCtx(ctx, field, 'field');
this.setFormData(ctx, ctx.parser.toFormValue(rule.value, ctx));
if (this.isMounted && !this.reloading) {
this.vm.$emit('change', ctx.field, rule.value, ctx.origin, this.api);
}
},
getParser(ctx) {
const list = this.fc.parsers;
return list[ctx.originType] || list[toCase(ctx.type)] || list[ctx.trueType] || BaseParser;
},
bindParser(ctx) {
ctx.setParser(this.getParser(ctx));
},
getType(alias) {
const map = this.fc.CreateNode.aliasMap;
const type = map[alias] || map[toCase(alias)] || alias;
return toCase(type);
},
noWatch(fn) {
if (!this.noWatchFn) {
this.noWatchFn = fn;
}
invoke(fn);
if (this.noWatchFn === fn) {
this.noWatchFn = null;
}
},
watchCtx(ctx) {
const vm = this.vm;
Object.keys(ctx.rule).filter(k => k[0] !== '_' && k[0] !== '$' && noneKey.indexOf(k) === -1).forEach((key) => {
const flag = key === 'children';
ctx.watch.push(vm.$watch(() => ctx.rule[key], (n, o) => {
if (this.loading || this.noWatchFn || this.reloading) return;
if (flag && ctx.parser.loadChildren === false) {
this.$render.clearCache(ctx);
this.nextRefresh();
return;
}
this.watching = true;
// if (key === 'hidden')
// ctx.updateKey(true);
// else
if (key === 'link') {
ctx.link();
return;
} else if (['props', 'on', 'nativeOn', 'deep'].indexOf(key) > -1) {
this.parseInjectEvent(ctx.rule, n || {});
if (key === 'props' && ctx.input) {
this.setFormData(ctx, ctx.parser.toFormValue(ctx.rule.value, ctx));
}
} else if (['emit', 'nativeEmit'].indexOf(key) > -1)
this.parseEmit(ctx, key === 'emit');
else if (['prefix', 'suffix'].indexOf(key) > -1)
n && this.loadFn(n, ctx.rule);
else if (key === 'type') {
ctx.updateType();
this.bindParser(ctx);
} else if (key === 'children') {
const flag = is.trueArray(n);
this.deferSyncValue(() => {
if (n !== o) {
this.rmSub(o, ctx);
this.$render.initOrgChildren();
}
flag && this.loadChildren(n, ctx);
this.vm.$emit('update', this.api);
});
}
this.$render.clearCache(ctx);
this.refresh();
this.watching = false;
}, {deep: !flag, sync: flag}));
});
this.watchEffect(ctx);
},
rmSub(sub, ctx) {
is.trueArray(sub) && sub.forEach(r => {
r && r.__fc__ && r.__fc__.parent === ctx && this.rmCtx(r.__fc__);
})
},
rmCtx(ctx) {
if (ctx.deleted) return;
const {id, field, input, name} = ctx;
if (ctx.input) {
Object.defineProperty(ctx.rule, 'value', {
value: ctx.rule.value,
writable: true
});
}
$del(this.ctxs, id);
$del(this.$render.tempList, id);
$del(this.$render.orgChildren, id);
$del(this.vm.ctxInject, id);
$del(this.formData, id);
$del(this.subForm, id);
$del(ctx, 'cacheValue');
input && this.rmIdCtx(ctx, field, 'field');
name && this.rmIdCtx(ctx, name, 'name');
if (input && !hasProperty(this.fieldCtx, field)) {
$del(this.form, field);
}
this.deferSyncValue(() => {
if (!this.reloading) {
if (ctx.parser.loadChildren !== false) {
if (is.trueArray(ctx.rule.children)) {
ctx.rule.children.forEach(h => h.__fc__ && this.rmCtx(h.__fc__));
}
}
if (ctx.root === this.rules) {
this.vm._renderRule();
}
}
}, input);
const index = this.sort.indexOf(id);
if (index > -1) {
this.sort.splice(index, 1);
}
this.$render.clearCache(ctx);
ctx.delete();
this.effect(ctx, 'deleted');
input && !this.fieldCtx[field] && this.vm.$emit('removeField', field, ctx.rule, this.api);
ctx.rule.__ctrl || this.vm.$emit('removeRule', ctx.rule, this.api);
return ctx;
},
})
}