一行代码胜百行,Sass 中的递归
| 没有评论
最近有个和列表相关的 UI 需求,要在选中的书签最左侧加上 4 个像素的高亮 border,如下图。难点在于设置各个层级的 padding-left。
先来看一下 DOM 结构:
DOM 是 pdfjs 生成的,修改 DOM 是一种选择。无论是把嵌套的 DOM 做扁平化处理,还是为每个层级的标签都加上新的 class,都需要去操作 DOM,消耗大,复杂度也高。因此用 CSS 解决是比较好的方案。
但是书签的 DOM 是嵌套结构,这意味着无法简单的设置 padding-left 来达到目的,我们需要为不同层级的书签设置不同的 padding-left。
比如,第 1 层的 padding-left 为 10px,第 2 层为 30px,第 3 层 50px,以此类推,每多一层嵌套多 20px,容易得到如下 Sass 代码:
#outlineView {
> .treeItem {
// 这是第 1 层
a {
padding-left: 10px;
}
> .treeItems {
> .treeItem {
// 这是第 2 层
a {
padding-left: 30px;
}
> .treeItems {
// 以此类推
...
}
}
}
}
}
手动硬编码 3 层已经是嵌套很深了。由于我们无法知道 pdf 的最高嵌套层数(世界之大无奇不有),因此只能尽可能多的提高覆盖率,也就是尽可能多的写嵌套,陷入嵌套地狱中去。
我们当然不能就这么陷进去,既然用了 Sass 就要用 Sass 的方式来解决。先设 N 为嵌套层级,那么,任意层均有 padding-left:(N - 1) * 20 + 10。
接下来思考一个问题,如果要在 Sass 中嵌入一段常用的 CSS,你会怎么做?
答案是用 @mixin/@include 来减少编码次数。
那如果在 @mixin 中 @include 自己,是不是就能递归了?
@mixin recursive-item-padding($cur, $end) {
> .treeItem {
a {
padding-left: #{($cur - 1) * 20 + 10}px;
}
@if $cur < $end {
> .treeItems {
@include recursive-item-padding($cur + 1, $end);
}
}
}
}
#outlineView {
// 随意递归 10 层
@include recursive-item-padding(1, 10);
}
完美。