该项目意在指导开发人员在json-editor之上新增自定义的format
想看该项目的demo的运行效果,请先安装node
,然后npm install
,然后就可以简单粗暴地把index.html
拖到浏览器了
增加自定义控件前,先浏览下demos/full-features/index.html
,看已有功能是否满足需求再决定是否有必要自定义
每一个editor都直接或间接继承自JSONEditor.AbstractEditor
(源码文件为editor.js),它的生命周期方法为:
init -> preBuild(表单元素未初始化) -> build(初始化表单元素) -> postBuild(表单元素已渲染) -> destroy
editor.js
: 所有editor的基类,附上官方对该类的说明
theme.js
: 构建表单元素常用的方法,通过这些方法构造的表单HTML结构可以套用多种样式框架
需要考虑是否需要重写以支持每个控件最基本的配置功能
-
enable / disable
-
getValue / setValue
-
showValidationErrors
最后记得值更改的时候调用onChange
以通知父级元素
TODO
TODO
可参考demos/custom-control-vue/index.js
JSONEditor.defaults.resolvers.unshift(function (schema) { ... })
如下:
JSONEditor.defaults.resolvers.unshift(function (schema) {
if (schema.type === "string" && schema.format === "custom-type") return "customType";
});
JSONEditor.defaults.editors.xxx = JSONEditor.AbstractEditor.extend({ ... })
其中xxx
为自定义类型名,如下:
JSONEditor.defaults.editors.customType = JSONEditor.AbstractEditor.extend({
vm: null, // 保存vue实例对象
setValue: function(value) {
...
},
build: function () {
...
}
});
以customType
为例
JSONEditor.defaults.editors.customType = JSONEditor.AbstractEditor.extend({
vm: null,
setValue: function(value) {
var changed = this.getValue() !== value;
if (changed) {
this.vm.$data.modelValue = value;
this.value = value;
}
this.onChange(changed); // 通知值发生变化 - 父级元素会自动刷新值
},
build: function () {
var self = this;
// 取得表单控件相关显示信息
if (!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
// 构造表单控件
this.wrapper = document.createElement('div');
this.wrapper.innerHTML = [
'<vue-comp :model-value="modelValue" :on-model-value-changed="modelValueChanged"></vue-comp>'
].join('');
this.control = this.theme.getFormControl(this.label, this.wrapper, this.description);
this.container.appendChild(this.control);
// 启动Vue
this.vm = new Vue({
el: this.control,
data: {
modelValue: '',
},
methods: {
modelValueChanged(newVal) {
self.setValue(newVal); // 同步json-editor value
}
}
});
}
});
接下来剖析下上面的代码
画
出表单控件
// 取得表单控件相关显示信息
if (!this.options.compact) this.header = this.label = this.theme.getFormInputLabel(this.getTitle());
if(this.schema.description) this.description = this.theme.getFormInputDescription(this.schema.description);
// 构造表单控件
this.wrapper = document.createElement('div');
this.wrapper.innerHTML = [
'<vue-comp :model-value="modelValue" :on-model-value-changed="modelValueChanged"></vue-comp>'
].join('');
this.control = this.theme.getFormControl(this.label, this.wrapper, this.description);
this.container.appendChild(this.control);
- 渲染Vue组件
this.vm = new Vue({
el: this.control,
...
});
- 同步数据 json-editor => Vue 组件
setValue: function(value) {
var changed = this.getValue() !== value;
if (changed) {
this.vm.$data.modelValue = value; // 同步数据: json-editor => Vue 组件
this.value = value;
}
this.onChange(changed); // 通知值发生变化 - 父级元素会自动刷新值
}
- 同步数据 Vue组件 =》json-editor
methods: {
modelValueChanged(newVal) {
self.setValue(newVal); // 同步数据:Vue组件 =》json-editor
}
}