无所谓使用什么样的瓶子,我就喝 evian
模型的核心是内容,所以这里的模型指的就是组件的模型,而模型的组织形式可以多种多样
模型?有没有个让我简单看懂的例子?
目的是手工配置方便,turing内定义了一种JSON结构,如:
Dept 模型的定义如下:
let views = {
//default这一段是基础属性会与以下其他的视图定义做合并输出
"default": {
id: { caption: "编号" },
name: { caption: "名称" },
pId: { caption: "父级部门编号" },
},
//以下视图定义根据业务需要,进行追加,每个属性即对于default的扩展
"默认列表:table": {
id: { },
name: { minWidth:150 },
pId: {},
},
"默认表单:form": {
id: {},
name: {},
pId: { xtype:"tree", url:"/api/dept" },
},
"查询": {
}
}
他们之间的关系是:继承。当然JSON里面比较通俗,就直接叫合并了
这样方便少写重复的配置属性,比如caption不论在表单、表格、搜索中的名字应该是统一的,一般就定义在default中。
而表格中可能会要显示几个额外的字段,就单独配置在表格模型里面。
那么大致使用方式应该如下:
let inst = new Dept();
let columns = inst.view("默认列表:table")
console.log(columns)
[
{"caption":"编号","title":"编号","key":"id","minWidth":120},
{"caption":"名称","title":"名称","key":"name","minWidth":150},
{"caption":"父级部门编号","title":"父级部门编号","key":"pId","minWidth":120}
]那么把这个模型直接赋值给组件即可
<Table :columns="columns" :data="rowData"></Table>模型能转成组件要的属性吗?
你可能会注意到“默认列表:table”,这里还有一个规则:
主要在于表格、表单所需要得到的实际组件属性不同,需要使用类型来指明具体是对应上一章节中组件的种类。
:table属性如果独立出来,可以更高的复用模型,但是对于长期维护来看,每种模型区分开来可以更好的降低相互的耦合,降低维护时多余的担心。
这个是来自组件库提供出来的 adapter 映射来实现的

此处略过180字,完整示例在最后附上
该怎么用它呢?
模型仅仅是JSON定义,那么要将它运行起来,需要与后台数据对接才行
能看图的尽量不bb

用起来很简单的样子
let inst = new Dept();
let rowData = async inst.findAll({ parentId:"00001" })后台该返回怎么样的数据结构才能接的上?
如:查列表的时候:
后台系统都是返回 [{},{},{}]
有的是返回{rows:[{}], total:1}
turing库在初始化时,可以重载请求干预的5个方法,实现后台结构返回数据可以对接上
这里还包括了请求字典数据、树形字典数据的干预方法。组件库中使用以上api,如:
import {ConnectItem,defaults} from'tg-turing'
defaults.afterFindAll[0] = function(data, action){
if (data.data instanceof Array === true) {
return data.data;
} else {
if (data.data.datas === undefined || data.data.datas[action.name] === undefined) {
console.error("请求返回数据异常", action.url, action, data);
}
data.data.datas[action.name].count = data.data.datas[action.name].totalSize;
data.data.datas[action.name].index = data.data.datas[action.name].pageNumber;
data.data.datas[action.name].size = data.data.datas[action.name].pageSize;
return data.data.datas[action.name];
}
}很有意思的秘籍,exports.defaults.afterFindAll[0],被覆盖的函数使用的是数组,原因是我们遇到了这样一个问题
index.js 初始化后,对函数进行覆盖
exports.defaults.getDictData = function(){}
而组件库中调用 afterFindAll 时,仍然为原始值,用不上初始化后覆盖的函数实现。
参考 axios 的defaults实现,发现将函数套用至数组内再覆盖即可。
!!!但是说来奇怪,现在已无法再重现这样的问题了,也就是说不用数组,直接覆盖函数也可用!!!
完整的模型定义示例 - Dept.js
import {DataAdapter} from 'tg-turing'
import TgAntd from 'tg-turing-antd' //基于antd风格的组件实现库
export default class extends DataAdapter {
constructor() {
super()
//视图定义
let views = {
//default这一段是基础属性会与以下其他的视图定义做合并输出
"default": {
id: { caption: "编号" },
name: { caption: "名称" },
pId: { caption: "父级部门编号" },
},
//以下视图定义根据业务需要,进行追加,每个属性即对于default的扩展
"默认列表:table": {
id: { },
name: { minWidth:150 },
pId: {},
},
"默认表单:form": {
id: {},
name: {},
pId: { xtype:"tree", url:"/api/dept" },
},
"查询": {
}
}
this.actions.findAll.url = "/api/dept";
this.actions.findAll.method = "get"
this.actions.save.url = "/api/dept/save";
this.actions.delete.url = "/api/dept/{id}";
this.actions.delete.method = "delete"
this.initView(views);
}
view(name, params) {
let props = name.split(":")
let antdtype = props[1];
return TgTgAntd.Adapter(antdtype, this.getView(props), params);
}
}完整API:
wisedu/turinggithub.com
争论:这些模型的配置究竟应该存储在哪里?

两种方案我们同时在不同的项目中实践
对此我只能说:各有利弊
- 存储在JS中:适合一个人负责完整项目。因为胜在简单
- 存储在Controller:适合多人协作,专业分工的场景,培训后效率更高。因为复杂在了边界上
感受一下异步调用:
let turing = window['tg-turing']
let inst = new turing.DataAdapterFactory.create()
export default {
data() {
return {
columns:[],
datasourceRules:[]
}
},
async mounted() {
await inst.load("/dsManager.do", "cxggsjy") //存储在后台controller中的cxggsjy模型
let columns = inst.view('grid:table');
columns.unshift({
key: 'opt',
title: "操作",
width: 120,
align: 'center'
});
this.columns = columns;
//自定义的校验也需要异步补充上
this.$nextTick(()=>{
//校验数据源名称是否被占用,编辑的情况下,不用校验名称
this.datasourceRules['group:[数据源信息]'].name.push({
validator: (rule, value, callback, source) => {
...
},
trigger: 'blur'
})
})
this.$refs.grid.reload()
},
};为啥之前都没提到 load 函数呢?
这是异步加载模型的方法,但后台如何存储模型、获取模型、后台用什么技术实现,又出现了一堆新问题。

所以异步加载的适配器,实际上是针对后端存储解决方案的特殊 数据适配器。
这里给出我们继承的代码🌰:
https://github.com/wisedu/turing/blob/master/DataBind/EMAPDataAdapter.jsgithub.com总结:
- 前端 接 组件
- 后端 接 数据
