布局一共有两个组件,一个是row
,另一个是col
,后者是通过render
函数来创建的,我们一一进行讲解。
Row
row
类似于bootstrap
中的container
,用来作为col
的容器,上面有一些动态的class
、style
,以及一个slot
用来放置col
,相对较为简单。
<template>
<div
class="el-row"
:style="style"
:class="[
justify !== 'start' ? 'is-justify-' + justify : '',
align !== 'top' ? 'is-align-' + align : '',
{
'el-row--flex': type === 'flex'
}
]"
>
<slot></slot>
</div>
</template>
其中,style
是一个计算属性,会根据gutter
这一prop
来改变,栏目之间的间隔,用来抵消col
造成的两边的padding
。
computed: {
style() {
var ret = {};
if (this.gutter) {
ret.marginLeft = `-${this.gutter / 2}px`;
ret.marginRight = ret.marginLeft;
}
return ret;
}
}
其他三个属性都是prop
:
props: {
type: String, // 可以使用flex,这样会采用flex布局
justify: { // flex 布局下的水平排列方式
type: String,
default: 'start'
},
align: { // flex 布局下的垂直排列方式
type: String,
default: 'top'
}
},
Col
列的实现只有一个col.js
,因为具体的组件是通过render
来生成的,因此,我们从render
入手,来解析col
组件。
render(h) {
let { style } = this; // style 是一个计算属性,将在下面的计算属性中讲解
let classList = [];
// span 栅格占据的列数,通过 width 来实现
// offset 栅格左侧的间隔格数,通过 margin-left 实现
// push 栅格向右移动格数,通过 left 实现
// pull 栅格向左移动格数,通过 right 实现
['span', 'offset', 'pull', 'push'].forEach(prop => {
if (this[prop]) {
classList.push(
prop !== 'span'
? `el-col-${prop}-${this[prop]}`
: `el-col-${this[prop]}`
);
}
});
// 不同屏幕大小下的适配,传入数字的话只会影响 span,还可以通过传入对象进行更多的控制
// xs <768px 响应式栅格数或者栅格属性对象
// sm ≥768px 响应式栅格数或者栅格属性对象
// md ≥992px 响应式栅格数或者栅格属性对象
// lg ≥1200px 响应式栅格数或者栅格属性对象
['xs', 'sm', 'md', 'lg'].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 (
<div
class={['el-col', classList]}
style={style}>
{this.$slots.default}
</div>
);
}
注:笔者目前对
render
的使用还没有太深入的研究,还流于表面,因此不评价这段的好坏。
计算属性
gutter
和style
都是计算属性。
computed: {
gutter() {
return this.$parent.gutter; // 返回父组件的 gutter 设置
},
style() {
var ret = {};
if (this.gutter) { // 如果有间隔,则改变 padding 值
ret.paddingLeft = this.gutter / 2 + 'px';
ret.paddingRight = ret.paddingLeft;
}
return ret;
}
}