1 | import DescriptionsRow from './descriptions-row';
|
2 | import { isFunction } from 'element-ui/src/utils/types';
|
3 |
|
4 | export default {
|
5 | name: 'ElDescriptions',
|
6 | components: {
|
7 | [DescriptionsRow.name]: DescriptionsRow
|
8 | },
|
9 | props: {
|
10 | border: {
|
11 | type: Boolean,
|
12 | default: false
|
13 | },
|
14 | column: {
|
15 | type: Number,
|
16 | default: 3
|
17 | },
|
18 | direction: {
|
19 | type: String,
|
20 | default: 'horizontal'
|
21 | },
|
22 | size: {
|
23 | type: String
|
24 |
|
25 | },
|
26 | title: {
|
27 | type: String,
|
28 | default: ''
|
29 | },
|
30 | extra: {
|
31 | type: String,
|
32 | default: ''
|
33 | },
|
34 | labelStyle: {
|
35 | type: Object
|
36 | },
|
37 | contentStyle: {
|
38 | type: Object
|
39 | },
|
40 | labelClassName: {
|
41 | type: String,
|
42 | default: ''
|
43 | },
|
44 | contentClassName: {
|
45 | type: String,
|
46 | default: ''
|
47 | },
|
48 | colon: {
|
49 | type: Boolean,
|
50 | default: true
|
51 | }
|
52 | },
|
53 | computed: {
|
54 | descriptionsSize() {
|
55 | return this.size || (this.$ELEMENT || {}).size;
|
56 | }
|
57 | },
|
58 | provide() {
|
59 | return {
|
60 | elDescriptions: this
|
61 | };
|
62 | },
|
63 | methods: {
|
64 | getOptionProps(vnode) {
|
65 | if (vnode.componentOptions) {
|
66 | const componentOptions = vnode.componentOptions;
|
67 | const { propsData = {}, Ctor = {} } = componentOptions;
|
68 | const props = (Ctor.options || {}).props || {};
|
69 | const res = {};
|
70 | for (const k in props) {
|
71 | const v = props[k];
|
72 | const defaultValue = v.default;
|
73 | if (defaultValue !== undefined) {
|
74 | res[k] = isFunction(defaultValue) ? defaultValue.call(vnode) : defaultValue;
|
75 | }
|
76 | }
|
77 | return { ...res, ...propsData };
|
78 | }
|
79 | return {};
|
80 | },
|
81 | getSlots(vnode) {
|
82 | let componentOptions = vnode.componentOptions || {};
|
83 | const children = vnode.children || componentOptions.children || [];
|
84 | const slots = {};
|
85 | children.forEach(child => {
|
86 | if (!this.isEmptyElement(child)) {
|
87 | const name = (child.data && child.data.slot) || 'default';
|
88 | slots[name] = slots[name] || [];
|
89 | if (child.tag === 'template') {
|
90 | slots[name].push(child.children);
|
91 | } else {
|
92 | slots[name].push(child);
|
93 | }
|
94 | }
|
95 | });
|
96 | return { ...slots };
|
97 | },
|
98 | isEmptyElement(c) {
|
99 | return !(c.tag || (c.text && c.text.trim() !== ''));
|
100 | },
|
101 | filledNode(node, span, count, isLast = false) {
|
102 | if (!node.props) {
|
103 | node.props = {};
|
104 | }
|
105 | if (span > count) {
|
106 | node.props.span = count;
|
107 | }
|
108 | if (isLast) {
|
109 |
|
110 | node.props.span = count;
|
111 | }
|
112 | return node;
|
113 | },
|
114 | getRows() {
|
115 | const children = ((this.$slots.default || []).filter(vnode => vnode.tag &&
|
116 | vnode.componentOptions && vnode.componentOptions.Ctor.options.name === 'ElDescriptionsItem'));
|
117 | const nodes = children.map(vnode => {
|
118 | return {
|
119 | props: this.getOptionProps(vnode),
|
120 | slots: this.getSlots(vnode),
|
121 | vnode
|
122 | };
|
123 | });
|
124 | const rows = [];
|
125 | let temp = [];
|
126 | let count = this.column;
|
127 |
|
128 | nodes.forEach((node, index) => {
|
129 | const span = node.props.span || 1;
|
130 |
|
131 | if (index === children.length - 1) {
|
132 | temp.push(this.filledNode(node, span, count, true));
|
133 | rows.push(temp);
|
134 | return;
|
135 | }
|
136 |
|
137 | if (span < count) {
|
138 | count -= span;
|
139 | temp.push(node);
|
140 | } else {
|
141 | temp.push(this.filledNode(node, span, count));
|
142 | rows.push(temp);
|
143 | count = this.column;
|
144 | temp = [];
|
145 | }
|
146 | });
|
147 |
|
148 | return rows;
|
149 | }
|
150 | },
|
151 | render() {
|
152 | const { title, extra, border, descriptionsSize, $slots } = this;
|
153 | const rows = this.getRows();
|
154 |
|
155 | return (
|
156 | <div class="el-descriptions">
|
157 | {
|
158 | (title || extra || $slots.title || $slots.extra)
|
159 | ? <div class="el-descriptions__header">
|
160 | <div class="el-descriptions__title">
|
161 | { $slots.title ? $slots.title : title}
|
162 | </div>
|
163 | <div class="el-descriptions__extra">
|
164 | { $slots.extra ? $slots.extra : extra }
|
165 | </div>
|
166 | </div>
|
167 | : null
|
168 | }
|
169 |
|
170 | <div class="el-descriptions__body">
|
171 | <table class={['el-descriptions__table', {'is-bordered': border}, descriptionsSize ? `el-descriptions--${descriptionsSize}` : '']}>
|
172 | {rows.map(row => (
|
173 | <DescriptionsRow row={row}></DescriptionsRow>
|
174 | ))}
|
175 | </table>
|
176 | </div>
|
177 | </div>
|
178 | );
|
179 | }
|
180 | };
|