提示:文章底部有完整的源代码,用Rollup编译后总体积只有2kb左右。童鞋有需要可以直接CTRL C拿。
我觉得前端的童鞋应该都知道或者使用网格布局吧?著名的UI库:bootstrap、element-ui、iview等。都提供网格布局。我们熟悉的这些库都是CSS预处理语言生成的网格布局。这是一个主流的实现方案,也符合前端开发的一个座右铭:能用CSS实现就尽量不要用JS实现。动机:熟悉网格布局实现原理的童鞋应该都清楚,网格布局的CSS代码量非常大,可以轻松达到30kb以上;虽然我们是用less这样的预处理语言写的,但是我们有一些编程语言的能力,可以使用循环和变量,大大减少我们写的代码量;但是,最终浏览器还是加载了生成的CSS。这个体积,像我这种对体积非常敏感的人,感觉有点大。那么,我们有没有办法大大减少网格布局的体积呢?这就是本文的主题:使用JS动态生成响应式网格布局。我们先来看两张效果图。这些是element-ui官方文档的Row和Col组件的示例,它们直接位于本文中实现的组件之下,没有任何修改。
正面网格布局
正面网格布局
要使用JS生成网格布局,我们需要动态创建样式表;使用JS创建样式表非常简单,只需创建一个style元素,然后将样式表字符串添加到style元素中,最后将style元素添加到头中。以下是createStylesheet函数的定义:
函数create stylesheet (id,stylesheetstr){ letel=document . getelementbyid(id)//避免重复创建同一个样式表,只创建if(!El){ El=document . createelement(‘ style ‘)El . id=id El . innerhtml=stylesheetstrdocument . head . appendchild(El)} }我们采用的网格布局是24列,与element-ui一致,这也是目前最主流的网格布局列数。我们需要生成从0到24的25列,当列占用的空间为0时隐藏。现在,让我们首先创建一个包含25个元素的数组。我们不需要关注数组中元素的值,我们只使用元素的索引。我使用数组是因为我不想使用for循环,而是更喜欢数组的遍历方法。
Constnulls=newarray (25)。fill (null)现在,我们定义一个函数getSpan来获取列宽。当列数为0时,元素被设置为不可见。
Constgetspan=(i,val)=I ` width : $ { val } ` 3360 ‘ display 3360 none ‘然后,我们创建用于生成列的函数genCol,该函数将列数转换为百分比,从而实现弹性宽度。不知道童鞋是不是分不清左右?[保持清白]
Export const cls=’x-col’ //class前缀constgencol=()=nulls.map (_,I)={ const val=` $ { I/24 * 100 } % ` return[`。$ {cls} _ span-$ {i} {$ } `,//列宽`。$ { CLS } _ pull-$ { I } { right 3360 $ { val };} `,//向左移动的宽度`。$ { CLS } _ push-$ { I } { left 3360 $ { val };} `,//要向右移动的宽度`。$ { CLS } _ offset-$ { I } { margin-left 3360 $ { val };} `//向右偏移宽度]。join(“”)}。join(‘ ‘)目前我们生成的布局是没有反应的,无论屏幕多宽都会占据固定的百分比宽度。那么,我们如何使布局具有响应性呢?媒体询问,该你出场了。现在,让我们首先定义一个根据窗口宽度生成布局的函数genColBySize。这个函数与上面的genCol函数非常相似,只是在类名中增加了一个size。童鞋应该能看懂吧?
const genColBySize=size=nulls . map((_,I)={ const val=` $ { I/24 * 100 } % ` return[`。$ { cls } _ $ { size }-span-$ { I } { $ { get span(I,val)};}`, `.$ { cls } _ $ { size }-pull-$ { I } { right : $ { val };}`, `.$ { cls } _ $ { size }-push-$ { I } { left : $ { val };}`, `.$ { cls } _ $ { size }-offset-$ { I } { margin-left : $ { val };}` ].join(“”)})。join(‘)我们与element-ui一致,将响应断点设置为五个,分别是: xs,sm,md,lg,XL;现在,我们生成响应布局并导出addStylesheet函数addstylesheet。
const genResponsiveCol=()=[‘ xs ‘],[‘sm ‘,768],[‘md ‘,992],[‘lg ‘,1200],[‘xl ‘,1920]]。map(_=_[1]` @ media(min-width : $ { _[1]} px){ $ { GenColbySize(_[0])} ` 3360 GenColbySize(_[0])。join(‘)//是为了减少两个生成函数的调用次数,避免不必要的调用。现在只会调用一次const rules tr=gen col()responsive col()export const add style sheet=()={ create style sheet(‘ x Gridlayout ‘,rules tr)}以上就是使用JS生成响应式网格布局的全部核心代码,不是很简单吗?现在,我已经将Row和Col组件的其余代码提供给童鞋了。为了节省空间,去掉了空行,但是可读性还是很高的。希望看过这篇文章的童鞋自己体会一下。Col.vue组件源代码:
Row.vue组件源代码:
Col组件样式是通过JS生成的,我们只需要row.scss样式文件。下面是源代码:x-row { display : flex;_ top { align-items : flex-start;} _ middle { align-items : center;} _ bottom { align-items : flex-end;} _start { justify-content:灵活启动;} _ end { justify-content : flex-end;} _ center { justify-content : center;} _ space-around { justify-content :空格-around;} _ space-between { justify-content : space-between;}}.x-col { word-wrap : break-word;}现在我们可以实现体积只有2kb的响应式网格布局。童鞋们懂吗?感谢阅读!
暂无讨论,说说你的看法吧