前言
layou組件也是使用element框架經常使用的組件,通過24分欄,可以快捷的完成佈局構建。layout組件構成爲el-row和el-col ,分別代表行的容器和列的容器。
el-row
export default {
name: 'ElRow',
componentName: 'ElRow',
props: {
tag: {
type: String,
default: 'div'
},
gutter: Number,
type: String,
justify: {
type: String,
default: 'start'
},
align: {
type: String,
default: 'top'
}
},
computed: {
style() {
const ret = {};
if (this.gutter) {
ret.marginLeft = `-${this.gutter / 2}px`;
ret.marginRight = ret.marginLeft;
}
return ret;
}
},
render(h) {
return h(this.tag, {
class: [
'el-row',
this.justify !== 'start' ? `is-justify-${this.justify}` : '',
this.align !== 'top' ? `is-align-${this.align}` : '',
{ 'el-row--flex': this.type === 'flex' }
],
style: this.style
}, this.$slots.default);
}
};
el-row的代碼相對較簡單。主要判斷是否是flex佈局,type屬性爲flex 啓用flex佈局。justify屬性是子元素的水平排列方式,與justify支持的屬性相同。 algin子元素垂直排列方式,支持top middle bottom。
計算屬性的style是row的左右margin 通過gutter 屬性計算出組件的負margin 。
gutter的作用是col組件之間產生間距,但是最左最右兩側的間距是0 所以這裏的負margin是抵消子組件col產生的最左和最右間距,最後通過render應用flex屬性和style屬性生成組件。
el-col
export default {
name: 'ElCol',
props: {
span: {
type: Number,
default: 24
},
tag: {
type: String,
default: 'div'
},
offset: Number,
pull: Number,
push: Number,
xs: [Number, Object],
sm: [Number, Object],
md: [Number, Object],
lg: [Number, Object],
xl: [Number, Object]
},
computed: {
gutter() {
let parent = this.$parent;
while (parent && parent.$options.componentName !== 'ElRow') {
parent = parent.$parent;
}
return parent ? parent.gutter : 0;
}
},
render(h) {
let classList = [];
let style = {};
if (this.gutter) {
style.paddingLeft = this.gutter / 2 + 'px';
style.paddingRight = style.paddingLeft;
}
['span', 'offset', 'pull', 'push'].forEach(prop => {
if (this[prop] || this[prop] === 0) {
classList.push(
prop !== 'span'
? `el-col-${prop}-${this[prop]}`
: `el-col-${this[prop]}`
);
}
});
['xs', 'sm', 'md', 'lg', 'xl'].forEach(size => {
if (typeof this[size] === 'number') {
classList.push(`el-col-${size}-${this[size]}`);
} else if (typeof this[size] === 'object') {
let props = this[size];
Object.keys(props).forEach(prop => {
classList.push(
prop !== 'span'
? `el-col-${size}-${prop}-${props[prop]}`
: `el-col-${size}-${props[prop]}`
);
});
}
});
return h(this.tag, {
class: ['el-col', classList],
style
}, this.$slots.default);
}
};
計算屬性計算節點的gutter屬性, gutter是從父級el-row節點得到的 ,通過不斷獲取父元素找到el-row的位置。
render函數的gutter計算左右兩側的padding,產生間距。
span offset pull push等屬性主要是el-rol柵格的偏移格數,通過獲取props屬性寫入class改變。
xs sm md 等屬性與響應式佈局有關,也是寫入class去改變。對應的width在var.scss文件可以查看。
渲染函數render主要將的到屬性放入class屬性,然後通過模板字符串的方式將組建渲染。
結論
Layou組件有el-row和el-col組成,本質是將width寬度24等分,然後通過flex gutter offset等屬性計算class調整佈局。有幾個小技巧記錄下,1,在gutter計算時,通過父組件的負margin抵消子組件的padding 2,在css計算時,通過scss 支持的for循環,減少了代碼的重複,感興趣的同學可以自行查看。