Vuetify有一套基于CSS FLEX-BOX的栅格系统。
Vuetify的栅格也是12栅格系统,其中的主要标签是:
v-container
,类似于各种前端框架的container,是一个把内容集中于屏幕中央的容器,可以加上fluid
属性扩展至全屏。
v-layout
,用于区分不同的大区域,是v-flex
元素的容器,大概近似于其他样式库的row。
v-flex
,就是响应式格子,这个标签会自动设置其子元素为flex: 1 1 auto
。
上边是官方文档的原文。具体还是要来看一看是怎么实现这些排布的。本文的目录如下:
- Grid系统
- 基础布局元素分析 v-app
- 基础布局元素分析 v-container
- 基础布局元素分析 v-layout
- v-layout API
- v-flex API
- v-spacer
Grid系统
基础布局元素分析 v-app
最直观的办法就是用这三个元素创建一个简单的页面,来看看浏览器里实际渲染的页面和样式。
<!DOCTYPE html>
<html lang="zhHans">
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.min.css" rel="stylesheet">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
</head>
<body>
<div id="app">
<v-app>
<v-container>
<v-layout>
<v-flex>
<div>ITEM</div>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify/dist/vuetify.js"></script>
<script>
new Vue({el: '#app'})
</script>
</body>
</html>
首先要知道的是:
Vuetify
作为Vue
的插件,要在Vue
内部才生效。所以外部需要#app
挂载Vue
,这和正常使用Vue
是一样的。
- 所有的
Vuetify
内容,都要被包裹在v-app
标签内才能正常发挥作用
然后来看一下浏览器中实际页面元素:
<div id="app">
v-app生成的标签
<div data-app="true" class="application theme--light" id="app">
<div class="application--wrap">
v-container生成的标签
<div class="container">
v-laygout生成的标签
<div class="layout">
<div class="flex">
<div>ITEM1</div>
</div>
</div>
</div>
</div>
</div>
</div>
查看了一下样式,最外层的<div id="app">
是Vue的挂载点,被设置成了所有padding和margin都是0的一个block。
之后的两层嵌套标签是v-app
生成的:来看一看其中奥妙:
<div data-app="true" ...>
标签的样式是display:flex
,而且没有任何其他的FLEX相关属性,很显然,这个是作为最外层的FLEX容器。默认是就是row
和 nowrap。
<div class="application--wrap">
也具有display:flex
属性,所以既是一个FLEX
ITEM(FLEX项目)也是一个FLEX容器,所以这是第二个嵌套FLEX容器。这其上还有其他相关的FLEX属性是:
flex-basis: auto
,说明宽度根据其中的项目来确定。
flex-direction: column
,注意,这里其内部包裹的FLEX项目排布变成了竖直方向。
flex-grow: 1
,说明允许放大。
flex-shrink: 1
,说明允许缩小。
通过分析这两个元素可以看到,v-app
这个元素直接将其中的所有内容包含在了一个两层嵌套,竖直排布的FLEX项目容器中。也就是说其中的所有内容,都是竖直排列的,显然是为了从上到下一块一块的排布内容。
可见这也是为什么Vuetify要求很多元素都要放在v-app
标签内部才生效,这是因为提供了页面的基础布局,在后台可能还有更多的东西依赖于这个元素。
基础布局元素分析 v-container
v-container
元素生成的页面元素是:<div class="container">
,也来看看其上的属性:
display: block
,说明不是FLEX容器
flex-basis: 100%
,可见这个元素强行撑开全部的页面
flex-grow: 1
,这个加上flex-basis: 100%
,让这个元素独占一行
flex-shrink: 1
,可缩小
通过这个元素可以发现,这个元素确实是起到分割的作用,每多一个这个元素,就相当于在FLEX容器里增加一个新区域。在行里就可以继续排布了。这个元素还有一个fluid
属性用于控制内容集中在视口中心还是平铺到整个宽度,经过看样式变化,加上fluid
其实就是取消了原本媒体查询在960px屏幕上最大宽度为900px和1264px屏幕上最大宽度1185px的样式。
基础布局元素分析 v-layout
v-layout
元素生成的页面元素是:<div class="layout">
,也来看看其上的属性:
display: flex
,是FLEX容器
flex-basis: auto
,由于上一层是100%宽,这一行也是100%宽
flex-grow: 1
,这个加上flex-basis: 100%
,让这个元素独占一行
flex-shrink: 1
,可缩小
flex-wrap: nowrap
,不允许换行,一行内排布
通过看其上的属性,可以发现这个元素在v-container
分割出的区域内,划出单独不允许换行的一行来排布元素。
基础布局元素分析 v-flex
最后是v-flex
元素,渲染的标签是<div class="flex">
,其属性是:
display: block
,不是FLEX容器
flex-basis: auto
,根据内容排布
flex-grow: 1
,这个加上flex-basis: 100%
,让这个元素独占一行
flex-shrink: 1
,可缩小
说明每一个v-flex
是v-container
这一行内的元素。
看完了这一层层元素,就比较清楚了,Vuetify先是强行使用v-app
排了一个竖向的布局,在其中用v-layout
分割出一个不换行的行,每一行里可以塞一个v-flex
元素,每个实际要布局的代码,就放在一行里的v-flex
元素中。
所以就可以把v-flex
元素认为是一个允许缩放的格子,在其中排布内容就行了。v-container
,由于不是FLEX容器,一般就无需控制了,而v-app
由Vuetify自动控制,我们也不用管。
分析到最后的结论就是,需要控制的是v-layout
和v-flex
的属性,就需要看一看Vuetify提供的这两个元素的属性(PROPS)了。
v-layout
v-layout
作为Flex容器,其设置主要就是Vuetify提供的设置flex相关属性的API。
在官网的Grid API可以查看相关的设置,除了tag
和id
属性之外,都是用于控制FLEX容器的属性,而且属性设置之后,就会被渲染为标签上的同名样式类,也方便使用Vue来控制。
v-layout API一览
标准W3C样式和属性 |
v-layout PROPS |
flex-direction 排布方向 |
column |
row |
reverse |
flex-wrap 是否换行 |
wrap,默认是nowrap |
justify-content 主轴对齐 |
justify-end |
justify-center |
justify-space-around |
justify-space-between |
justify-start |
align-items 交叉轴对齐 |
align-baseline |
align-center |
align-end |
align-start |
fill-height,这个对应的是align-items:stretch |
align-content 交叉轴多行对齐 |
align-content-center |
align-content-end |
align-content-space-around |
align-content-space-between |
align-content-start |
好像没有在这种情况下对应stretch的内容。不过试验了一下,对排版没有任何影响。 |
tag 实际渲染标签 |
用来控制将这个标签实际渲染成什么元素,比如tag="p" 就会渲染成P标签。 |
display: flex FLEX容器类型 |
d-{type},比如d-inline-flex就对应display: inline-flex,默认就是d-flex。 |
id 标准DOM属性 |
id属性,会被原样渲染到实际的标签中。 |
上边的所有除了写默认值的以外,其他的默认值都是false
,即不设置就相当于是false
,会让样式采用CSS FLEX标准默认的样式,比如不设置column
则默认就是row
。
v-flex
既然相当于一个格子,参考其他UI库的经验,肯定会有的就是控制在不同屏幕断点下的宽度的属性了。然后由于是FLEX项目,肯定还会有自身的几个对应标准FLEX属性的属性。此外还有偏移量。
先列出全部API然后分开来看:
v-flex API一览
API |
解释 |
(size)(1-12) |
断点紧跟1-12大小,表示不同屏幕宽度下的格子宽度,断点有五个:xs|sm|md|lg|xl,实际写法比如xs12 md6 |
align-self-baseline |
对应 align-self FLEX标准属性 |
align-self-end |
align-self-start |
align-self-center |
grow |
是否占据剩余空间,设置上该属性相当于flex-grow:1。 |
shrink |
是否缩小以适合空间,设置上该属性相当于flex-shrink: 1。 |
order-(size)(1-12) |
在不同大小屏幕之下对应的顺序,对应标准的order属性。 |
offset-(size)(0-12) |
在不同大小屏幕之下的偏移量,使用方法和其他UI库很像。写法是offset-xs1,注意这个也是从小到大覆盖的,单独使用offset-xs1表示所有情况下都缩进一行1/12的距离。 |
tag 实际渲染标签 |
用来控制将这个标签实际渲染成什么元素,比如tag="p" 就会渲染成P标签。 |
id 标准DOM属性 |
id属性,会被原样渲染到实际的标签中。 |
v-flex
上除了标准FLEX属性,和有时候能用到的偏移之外,最重要的属性就是断点。有了断点配合对应的宽度,才能够实现一些特殊的排版。由于Vuetify里的断点设计成可以通过JS代码方便的控制,因此也是构成Grid系统的一个关键部分,需要单独来看。
v-spacer
v-spacer
是一个空白的div元素,可以用来进行分离挨的近的元素。一般用在FLEX排版的内容当中。典型的应用就是一个标题栏。
到现在就可以进行简单的排版了,但是如果要通过断点改变FLEX的属性,还需要针对断点编写媒体查询的CSS代码。既然使用了前端UI库,当然不想再写额外的CSS代码了,Vuetify提供了使用JS代码监听断点进而改变属性的功能。在下篇中来看一下断点,就可以非常灵活的进行排版了。