概述
在前端布局中,栅格系统还是很常见的,对于响应式布局,尤为重要,下面记录一下实现vue栅格系统组件。 我们采用了24栅格系统,将区域进行24等分,这样可以轻松应对大部分布局问题。使用栅格系统进行网页布局,可以使页面排版美观、舒适。(参考多数组件库的实现以及经典的bootstrap)
定义了两个概念,行row和列col,具体使用方法如下:
- 使用
row在水平方向创建一行 - 将一组
col插入在row中 - 在每个
col中,键入自己的内容 - 通过设置
col的span参数,指定跨越的范围,其范围是1到24 - 每个
row中的col总和应该为24
下面的实现,参考iview组件库的栅格系统插件中的使用来实现的,多数情况下,使用方式是一致的。无非是实现方式的不同。
实现
文件目录
Row.vue
<template>
<div class="g-row" :style="rowStyle">
<slot></slot>
</div>
</template>
<script>
export default {
// 将Row组件注入到col组件中
provide() {
return {
rowInstance: this,
};
},
props: {
// 间隙
gutter: {
type: [String, Number],
},
// 对应弹性布局justify-content
justify: {
type: String,
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return [
"start",
"end",
"center",
"space-around",
"space-between",
].includes(value);
},
},
// 对应弹性布局中align-items
align: {
type: String,
validator: function (value) {
// 这个值必须匹配下列字符串中的一个
return ["flex-start", "center", "flex-end", "stretch"].includes(value);
},
},
},
computed: {
// style属性
rowStyle() {
return {
marginLeft: -this.gutter / 2 + "px",
marginRight: -this.gutter / 2 + "px",
justifyContent: this.justify,
alignItems: this.align,
};
},
},
};
</script>
<style lang="less">
.g-row {
display: flex;
flex-wrap: wrap;
}
</style>
Col.vue
<template>
<div :class="colClass" :style="colStyle">
<slot></slot>
</div>
</template>
<script>
export default {
// Row组件的实例
inject: ["rowInstance"],
props: {
// 所占具体空间份数
span: {
type: [String, Number],
},
// 对应弹性布局汇中的order属性
order: {
type: [String, Number],
},
// 偏移量
offset: {
type: [String, Number],
},
// 对应弹性布局flex属性
flex: {
type: [String, Number],
},
// 下面为响应式布局属性
xs: {
// <576px
type: [String, Number],
},
sm: {
// ≥576px
type: [String, Number],
},
md: {
// ≥768px
type: [String, Number],
},
lg: {
// ≥992px
type: [String, Number],
},
xl: {
// ≥1200px
type: [String, Number],
},
xxl: {
// ≥1600px
type: [String, Number],
},
},
data() {
return {};
},
computed: {
colClass() {
return [
"g-col",
this.xs ? `g-col-xs-${this.xs}` : "",
this.sm ? `g-col-sm-${this.sm}` : "",
this.md ? `g-col-md-${this.md}` : "",
this.lg ? `g-col-lg-${this.lg}` : "",
this.xl ? `g-col-xl-${this.xl}` : "",
this.xxl ? `g-col-xxl-${this.xxl}` : "",
];
},
// style
colStyle() {
return {
flex: this.span
? `calc(100% / 24 * ${this.span})`
: this.flex
? this.flex
: "",
maxWidth: this.span ? `calc(100% / 24 * ${this.span})` : "none",
paddingLeft: this.rowInstance.gutter / 2 + "px",
paddingRight: this.rowInstance.gutter / 2 + "px",
order: this.order * 1,
marginLeft: this.offset ? `calc(100% / 24 * ${this.offset})` : "",
};
},
},
};
</script>
index.js
import Row from "./Row.vue";
import Col from "./Col.vue";
export { Row, Col };
使用
App.vue
<template>
<div class="app">
<div class="row">
<Row :gutter="100" align="bottom" justify="end">
<Col span="6" order="4"><div class="content one">1</div></Col>
<Col span="6" order="3"><div class="content two">2</div></Col>
<Col span="6" order="6"><div class="content three">3</div></Col>
</Row>
</div>
<div class="row">
<Row>
<Col :xs="24" :sm="4" :md="2" :lg="8" :xxl="24"
><div class="content one">1</div></Col
>
<Col :xs="24" :sm="16" :md="12" :lg="8" :xxl="24"
><div class="content two">2</div></Col
>
<Col :xs="24" :sm="4" :md="6" :lg="8" :xxl="24"
><div class="content three">3</div></Col
>
</Row>
</div>
</div>
</template>
<script>
import { Row, Col } from "./components/Row/index.js";
export default {
components: { Row, Col },
};
</script>
<style lang="less">
* {
margin: 0;
padding: 0;
}
.row {
width: 70%;
margin: 20px auto;
border: 1px solid #000;
overflow: hidden;
height: 300px;
.content {
height: 30px;
line-height: 30px;
}
.one {
background-color: pink;
}
.two {
background-color: #008c8c;
}
.three {
background-color: greenyellow;
}
.four {
background-color: rgb(122, 122, 218);
}
}
</style>
common.less
//只要做响应式的配置,只列出部分类名
@media (max-width: 576px) {
.g-col-xs-1 {
flex: calc(100% / 24 * 1);
max-width: calc(100% / 24 * 1);
}
.g-col-xs-2 {
flex: calc(100% / 24 * 2);
max-width: calc(100% / 24 * 2);
}
.g-col-xs-3 {
flex: calc(100% / 24 * 3);
max-width: calc(100% / 24 * 3);
}
.g-col-xs-4 {
flex: calc(100% / 24 * 4);
max-width: calc(100% / 24 * 4);
}
.g-col-xs-6 {
flex: calc(100% / 24 * 6);
max-width: calc(100% / 24 * 6);
}
.g-col-xs-8 {
flex: calc(100% / 24 * 8);
max-width: calc(100% / 24 * 8);
}
.g-col-xs-12 {
flex: calc(100% / 24 * 12);
max-width: calc(100% / 24 * 12);
}
.g-col-xs-16 {
flex: calc(100% / 24 * 16);
max-width: calc(100% / 24 * 16);
}
.g-col-xs-24 {
flex: calc(100% / 24 * 24);
max-width: calc(100% / 24 * 24);
}
}
@media (min-width: 577px) {
.g-col-sm-1 {
flex: calc(100% / 24 * 1);
max-width: calc(100% / 24 * 1);
}
.g-col-sm-2 {
flex: calc(100% / 24 * 2);
max-width: calc(100% / 24 * 2);
}
.g-col-sm-3 {
flex: calc(100% / 24 * 3);
max-width: calc(100% / 24 * 3);
}
.g-col-sm-4 {
flex: calc(100% / 24 * 4);
max-width: calc(100% / 24 * 4);
}
.g-col-sm-6 {
flex: calc(100% / 24 * 6);
max-width: calc(100% / 24 * 6);
}
.g-col-sm-8 {
flex: calc(100% / 24 * 8);
max-width: calc(100% / 24 * 8);
}
.g-col-sm-12 {
flex: calc(100% / 24 * 12);
max-width: calc(100% / 24 * 12);
}
.g-col-sm-16 {
flex: calc(100% / 24 * 16);
max-width: calc(100% / 24 * 16);
}
.g-col-sm-24 {
flex: calc(100% / 24 * 24);
max-width: calc(100% / 24 * 24);
}
}
@media (min-width: 768px) {
.g-col-md-1 {
flex: calc(100% / 24 * 1);
max-width: calc(100% / 24 * 1);
}
.g-col-md-2 {
flex: calc(100% / 24 * 2);
max-width: calc(100% / 24 * 2);
}
.g-col-md-3 {
flex: calc(100% / 24 * 3);
max-width: calc(100% / 24 * 3);
}
.g-col-md-4 {
flex: calc(100% / 24 * 4);
max-width: calc(100% / 24 * 4);
}
.g-col-md-6 {
flex: calc(100% / 24 * 6);
max-width: calc(100% / 24 * 6);
}
.g-col-md-8 {
flex: calc(100% / 24 * 8);
max-width: calc(100% / 24 * 8);
}
.g-col-md-12 {
flex: calc(100% / 24 * 12);
max-width: calc(100% / 24 * 12);
}
.g-col-md-16 {
flex: calc(100% / 24 * 16);
max-width: calc(100% / 24 * 16);
}
.g-col-md-24 {
flex: calc(100% / 24 * 24);
max-width: calc(100% / 24 * 24);
}
}
@media (min-width: 992px) {
.g-col-lg-1 {
flex: calc(100% / 24 * 1);
max-width: calc(100% / 24 * 1);
}
.g-col-lg-2 {
flex: calc(100% / 24 * 2);
max-width: calc(100% / 24 * 2);
}
.g-col-lg-3 {
flex: calc(100% / 24 * 3);
max-width: calc(100% / 24 * 3);
}
.g-col-lg-4 {
flex: calc(100% / 24 * 4);
max-width: calc(100% / 24 * 4);
}
.g-col-lg-6 {
flex: calc(100% / 24 * 6);
max-width: calc(100% / 24 * 6);
}
.g-col-lg-8 {
flex: calc(100% / 24 * 8);
max-width: calc(100% / 24 * 8);
}
.g-col-lg-12 {
flex: calc(100% / 24 * 12);
max-width: calc(100% / 24 * 12);
}
.g-col-lg-16 {
flex: calc(100% / 24 * 16);
max-width: calc(100% / 24 * 16);
}
.g-col-lg-24 {
flex: calc(100% / 24 * 24);
max-width: calc(100% / 24 * 24);
}
}
@media (min-width: 1200px) {
.g-col-xl-1 {
flex: calc(100% / 24 * 1);
max-width: calc(100% / 24 * 1);
}
.g-col-xl-2 {
flex: calc(100% / 24 * 2);
max-width: calc(100% / 24 * 2);
}
.g-col-xl-3 {
flex: calc(100% / 24 * 3);
max-width: calc(100% / 24 * 3);
}
.g-col-xl-4 {
flex: calc(100% / 24 * 4);
max-width: calc(100% / 24 * 4);
}
.g-col-xl-6 {
flex: calc(100% / 24 * 6);
max-width: calc(100% / 24 * 6);
}
.g-col-xl-8 {
flex: calc(100% / 24 * 8);
max-width: calc(100% / 24 * 8);
}
.g-col-xl-12 {
flex: calc(100% / 24 * 12);
max-width: calc(100% / 24 * 12);
}
.g-col-xl-16 {
flex: calc(100% / 24 * 16);
max-width: calc(100% / 24 * 16);
}
.g-col-xl-24 {
flex: calc(100% / 24 * 24);
max-width: calc(100% / 24 * 24);
}
}
@media (min-width: 1600px) {
.g-col-xxl-1 {
flex: calc(100% / 24 * 1);
max-width: calc(100% / 24 * 1);
}
.g-col-xxl-2 {
flex: calc(100% / 24 * 2);
max-width: calc(100% / 24 * 2);
}
.g-col-xxl-3 {
flex: calc(100% / 24 * 3);
max-width: calc(100% / 24 * 3);
}
.g-col-xxl-6 {
flex: calc(100% / 24 * 6);
max-width: calc(100% / 24 * 6);
}
.g-col-xxl-8 {
flex: calc(100% / 24 * 8);
max-width: calc(100% / 24 * 8);
}
.g-col-xxl-12 {
flex: calc(100% / 24 * 12);
max-width: calc(100% / 24 * 12);
}
.g-col-xxl-24 {
flex: calc(100% / 24 * 24);
max-width: calc(100% / 24 * 24);
}
}
总结
栅格系统组件,更多在于css的用法,以及弹性布局和盒模型的运用。