editor.vue
4.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<script>
import { get, set, cloneDeep } from '../utils';
import { renderContext } from '../utils/vnode';
// 标题渲染
function headerRender(h, context, item) {
const headerSlot = context.scopedSlots[`header-${item.prop}`];
return function(scope) {
// 自定义具名插槽
if (headerSlot) {
return headerSlot(scope);
}
// 自定义渲染函数
if (item.header) {
return item.header(item, h, scope);
}
// 默认取值
return item.label;
};
}
// 单元格渲染
function cellRender(h, context, item) {
const cellSlot = context.scopedSlots[`cell-${item.prop}`];
return function(scope) {
const value = get(scope.row, item.prop);
// 自定义具名插槽
if (cellSlot) {
return cellSlot({ item, value, index: scope.$index, ...scope });
}
// 自定义渲染函数
if (item.render) {
return item.render(value, scope.row, h, scope.$index);
}
// 默认取值
return get(scope.row, item.prop);
};
}
// 编辑器渲染
function editorRender(h, context, item) {
const editorSlot = context.scopedSlots[`editor-${item.prop}`];
const contentProps = context.props || {};
return function(scope) {
const value = get(scope.row, item.prop);
// 自定义具名插槽
if (editorSlot) {
return editorSlot({ item, value, index: scope.$index, ...scope });
}
// 默认
const vnode = h(item.is, {
attrs: item.attrs,
props: { ...(item.props || {}), value },
on: {
input(val) {
if (get(contentProps, 'editor.deep') === true) {
if (item.prop.indexOf('.') > -1 || item.prop.indexOf('[') > -1) {
let separator = '';
if (item.prop.indexOf('.') > -1) {
separator = '.';
} else if (item.prop.indexOf('[') > -1) {
separator = '[';
}
const path = item.prop.split(separator);
const bindProp = path[0];
const propValue = cloneDeep(scope.row);
set(propValue, item.prop, val);
vnode.componentInstance.$set(scope.row, bindProp, propValue[bindProp]);
} else {
// set(scope.row, item.prop, val);
scope.row[item.prop] = val;
}
} else {
scope.row[item.prop] = val;
// set(contentProps.data, `[${[scope.$index]}]${item.prop}`, val);
}
if (item.on && item.on.input) {
item.on.input(val);
}
},
},
});
return vnode;
};
}
// 跟进columns生成列
function createElTableColumns(h, context, columns) {
const props = context.props || {};
const editorConfig = props.editor || {};
return columns.map((item, index) => {
const { attrs, on, ...props } = item;
const editorMatch = editorConfig.inputs.find(i => i.prop === item.prop);
// 处理插槽
const scopedSlots = {
header: headerRender(h, context, item),
default: editorMatch ? editorRender(h, context, editorMatch) : cellRender(h, context, item),
};
return h('el-table-column', { key: index, attrs, props, on, scopedSlots });
});
}
export default {
name: 'TableEditor',
functional: true,
render(h, context) {
console.log(context);
const props = context.props || {};
let scopedSlots = context.scopedSlots || {};
// 如有默认插槽则相当于直接写el-table
if (scopedSlots.default) {
return h('el-table', context);
}
const columns = props.columns || [];
// 通过columns快速生成el-table-column
const elTableColumns = createElTableColumns(h, context, columns);
// 前置插槽
const prependSlot = scopedSlots.prepend ? scopedSlots.prepend() : '';
// 左侧插槽
const leftSlot = scopedSlots.left ? scopedSlots.left() : '';
// 右侧插槽
const rightSlot = scopedSlots.right ? scopedSlots.right() : '';
// 后置插槽
const appendSlot = scopedSlots.append ? scopedSlots.append() : '';
// 渲染组件时移除当前组件特有的props,避免透传不必要的参数
delete context.columns;
return h('el-table', renderContext(context), [prependSlot, leftSlot, ...elTableColumns, rightSlot, appendSlot]);
},
};
</script>