14.NiceGUI教程,一次讲清楚页面布局
0.系列文章
- 系列文章入口(欢迎关注):
nicegui最佳实践系列 - 示例代码位置:
- GitHub地址:
Github[https://github.com/thekingofhero2/nicegui-enough.git] - 便于访问,也在码云上进行了同步:
Gitee[https://gitee.com/thekingofhero/nicegui-enough.git]
- 演示系统地址:
http://niceadmin.qiaojianpan.cn
账号:admin
密码: 123456
003.一次讲清楚NiceGUI页面布局
其实原本计划是继续“从0开始搭建一个后台管理系统”的开发,讲refresh和数据绑定,但是群里的好朋友希望我深入讲一下NiceGUI的页面布局和样式,既然有朋友给建议,那我就从善如流吧(毕竟现在群里人少,对,就是邀请你关注公众号,加我进群的意思,哈哈!)
老生常谈的一句话 “您的转发是我的动力”,话不多说,现在开始!
3.1 先从官网开始
- 既然做NiceGUI的系统,那首先要看看NiceGUI官网关于页面布局是怎么讲的。
官网地址(https://nicegui.io/documentation/section_page_layout)
好吧,东西太多了,其实刚开始做系统,没有前端知识前,只要了解Grid、Row、Column三样就好,我的宗旨一直都是先入门、再优化。(再次吐槽NiceGUI的官方文档如此凌乱)
- 既然NiceGUI前端是建立在Quasar之上的,那我们再看一下Quasar官网是怎么讲布局的(这里我看的是中文站,不是官方原版)。
quasar中文站地址(https://www.quasar-cn.cn/layout/grid/introduction-to-flexbox)
Quasar的文档就要舒服多了,就是没有前端基础看上去有些无从下手。不过别害怕,后面会讲清楚怎么用。
值得注意的是,Quasar官网提供了一个十分有用的工具----“Flex在线体验”。通过对父容器、子容器设置不同的CSS类,可以直观地看到效果的变化,当效果符合预期时,可以把对应的CSS类写在你NiceGUI组件中的**组件.classes()**中,效果是一样的。
3.2 确实需要补一点对前端的认识
秉承着“够用就好”的原则,我这里只讲我的理解,不会过深的研究标准和语法。我会结合着NiceGUI中的实现来讲,举例也许会不恰当,海涵。
3.2.1 盒子模型(Box Model)
这里说的盒子可以理解为一个矩形框,网页就是一个巨大的画布,里面的元素无论是图片、按钮、链接等等都被放在各自的矩形框中,所谓页面布局,实际上就是把这些矩形框摆到特定的位置上。
- 从图上能发现,要想改变盒子的形态,首先会有两个属性:宽(height)和高(width)。那么在NiceGUI中,如何直接地限定组件地宽和高呢?用w-和h-分别限定宽度和高度,中括号内写入占用多少个像素格(px)。(多了不说,先学明白像素就行)
###3.2.1 盒子模型
ui.button("瘦按钮").classes("w-[50px] h-[100px]")
ui.button("胖按钮").classes("w-[100px] h-[100px]")
ui.button("高按钮").classes("w-[100px] h-[200px]")
ui.button("矮按钮").classes("w-[100px] h-[50px]")
效果如下。
- 外边距、内边距
上面提到的盒子或者矩形框,我们在以后统称为容器。在NiceGUI里,常用的容器就是行容器和列容器。
那么所谓外边距(margin),指的是“控件”到“外部容器”间的距离。
所谓内边距(padding),指的就是“控件边框”到“控件内容”间的距离。
至于边框(border),咱们不是前端课程,我也就不讲了。
with ui.row().classes("bg-red"):
ui.button("外边距按钮").classes("w-[100px] h-[100px] q-ma-lg")
#ui.label("通过q-ma-lg,设置外边距(margin)、四周(all)、巨大间距(lg),所以露出了row的底色“红色”")
with ui.row().classes("bg-red"):
ui.button("内边距按钮").classes("w-[100px] h-[100px] q-pa-lg")
#ui.label("通过q-pa-lg,设置内边距(padding)、四周(all)、巨大间距(lg),所以文字被挤压换行了")
效果如下。
Quasar的官网解释的非常详细,可以自行查阅(内外边距查看“样式” ->“间距”;边框查阅“样式”-“其他CSS辅助类”->“Border Related”)
值得一说的是,前端同学的调试方法。因为容器(行、列)都是看不见摸不着的存在,一般都给它赋予一个背景色,方便调试。在NiceGUI中设置行列的背景色十分简单,比如上面代码中“ui.row().classes(“bg-red”)”就把这一行的背景色设置为红色。
3.2.2 弹性盒子(Flex Box)
弹性盒子是在盒子模型之上发展而来,之所以称之为“弹性”,主要是为了应对不同屏幕大小、不同设备间的展示效果。这也就解释了,为什么有些网站用PC打开很漂亮、用手机打开各种扭曲,原因就是没考虑“弹性”布局。这里不做展开,你需要知道有这么个事情就好,因为Quasar是基于弹性盒子实现的,所以相信自己,通过一些Quasar的预置类型设置就能做出一个适配移动端的网页。
3.2.3 网格布局 (Grid Layout)
看过我前面文章的同学可能还有印象,我推荐NiceGUI新朋友直接使用网格布局,相对而言简单、直接。网格布局只要设定好columns属性,就表示网页被横向均分成多少个列,再通过col-span-X类型设置,就可以明确表示某一空间占多宽。至于rows属性,目前我觉得没有columns用的多。
下面的代码虽然简单,但是仍描述了几个情形:
- columns=12,表示横向分为12列,满(或即将超过)12列则自动换行
- 行高取的是这一行内所有元素的最大值。
with ui.grid(columns=12):
#通过设置col-span-X,限定每一列宽度
ui.button("普通按钮").classes("col-span-1")
ui.button("普通按钮").classes("col-span-2")
ui.button("普通按钮").classes("col-span-6")
#因为再+8一行放不下,所以自动换行
ui.button("普通按钮").classes("col-span-8")
ui.button("普通按钮").classes("col-span-4")
#正好满足12列,换行;其中一个按钮高度设置为300px,则整行都被设置高度为300px
ui.button("普通按钮").classes("col-span-1 h-[300px]")
ui.button("普通按钮").classes("col-span-1")
3.2.4 行与列–行(Row & Column)
行与列是最基本的容器,我这里把行和列常用的对齐方式做下介绍。
- 网格行的基本用法。没有太多可说的,只要记住经常把**“w-full”**放在classes中,表示这个容器独占一行。当发现布局问题时可以多试试w-full,比如页面显示不完整、classes设置无效等等,很多时候都是它导致的。
ui.label("3.2.4 网格行").classes("text-h2")
with ui.row().classes("bg-red"):
ui.button("普通按钮")
with ui.row().classes("w-full bg-red"):
ui.button("普通按钮")
with ui.row().classes("w-full bg-red"):
ui.button("普通按钮").classes("h-[300px]")
ui.button("普通按钮")
- 对齐方式
对齐方式还是有些问题需要说明一下的。对齐方式分为横向排布和纵向排布。有的同学要问了,我们讲的是行对齐方式,为什么还会有纵向排布?看这个图你就明白了。当一个Row有了“高度”设置之后,里面的控件就会涉及到纵向排布的问题。
#2.对齐方式,这里的“w-full”很重要,否则看不到效果
with ui.row().classes("w-full bg-secondary items-center h-[300px]"):
ui.button("普通按钮")
ui.button("普通按钮")
ui.button("普通按钮")
with ui.row().classes("w-full bg-secondary justify-center h-[300px]"):
ui.button("普通按钮")
ui.button("普通按钮")
ui.button("普通按钮")
- 横向排布(justify-start/center/end/around/between/evenly)
对于“行”来说,横向排布指的就是内部控件的横向摆放方式。
start顶格摆放。
center居中摆放。
end右对齐摆放。
aroundRow里的组件四周都留空白。
between两头顶格,均匀分布。
evenly等距分布。 - 纵向排布(items-start/center/end)
对于“行”来说,只有有“高度”的行,纵向分布才会显示出效果。
start顶上框摆放。
center居中摆放。
end抵下框摆放。
3.2.5 行与列–列(Row & Column)
本来想单拆开介绍一下列,但是感觉没有太大必要,行、列密不可分,绝大部分属性是一样的,但是关于对齐方式还是有必要讲一下。先看下面的例子。
同样都是“items-start”,在Row中元素的排布是沿着纵向顶格开始,在Column中元素的排布是沿着横向从最左面开始,这是为什么呢?其实只要引入一个“主轴”和“交叉轴”的概念就好理解了。
- 主轴
主轴就是沿着元素放置的方向延伸。 - 交叉轴
记住垂直于主轴方向的延伸。
其实在NiceGUI中只要记住,Row容器的主轴方向是横着的、Column容器的主轴方向是竖着的就好了。而在上面讲的“justify-*”和“items-*”其实并不是横向布局和纵向布局,对应的应该是“主轴”布局和“交叉轴”布局,这样想就会理解他的布局方式了。(好好想想,想不通可以找我聊聊,共同进步嘛~)
3.4 本章小结
感谢提问的同学,其实你们每次提问,我都会不自觉地翻一下官方文档,怕自己的回答有太大的错误,无形中也对自己的知识进行了检验。
不知道讲清了没有?没有的话后面再补一篇(偷笑)
为了方便大家学习交流,特别建立了“nicegui交流群”,有需要的同学可以后台留言~