其他实用函数
约 2190 字大约 7 分钟
2025-04-18
一、called-from
输出调用堆栈信息
called-from
用于返回当前函数的调用堆栈信息 。具体来说,called-from
属性包含以倒序调用当前函数的函数列表,其中第一项是最深的函数。类似于 JavaScript 中的 console.trace()
。
我们来回顾一下 JavaScript 中的 console.trace()
方法:
function outer() {
middle();
}
function middle() {
inner();
}
function inner() {
console.trace(); // 打印调用堆栈
}
outer();
console.trace VM2111:10
inner @ VM2111:10
middle @ VM2111:6
outer @ VM2111:2
(anonymous) @ VM2111:13
called-from
的使用方法与 console.trace()
类似,它返回一个字符串,其中包含以倒序调用当前函数的函数列表。
foo()
bar()
bar()
baz()
baz()
return called-from
foo() // => bar foo
二、current-media()
输出当前媒体查询信息
current-media()
用于返回当前媒体查询信息(@media()
)。具体来说,current-media()
属性包含当前媒体查询的字符串。如果块上方没有 @media
,则返回 ''
。
@media only screen and (min-width: 1024px)
current-media()
// => '@media (only screen and (min-width: (1024px)))'
三、+cache(keys...)
+cache(keys...)
是 Stylus 中的一个高级混合(mixin)功能,用于创建带有缓存机制的样式块,可以避免重复生成相同的 CSS 代码。第一次调用的时候,Stylus 会将生成的 CSS 代码缓存起来,后续调用的时候,会使用相同的参数对第一次调用的结果进行@extend
。
具体来说,+cache(keys...)
可以传入多个参数,多个参数组合成一个缓存键,用于标识当前 mixin。如果 keys
相同,则返回相同的结果。keys
的顺序不同会被视为不同的缓存键。
实现原理
Stylus 在编译时会:
- 为每个 +cache 块创建唯一的哈希标识
- 检查是否已有相同哈希的样式输出
- 如果存在则跳过,不存在则生成并记录
示例
size($width, $height = $width)
+cache('w' + $width)
width: $width
+cache('h' + $height)
height: $height
.a
size: 10px 20px
.b
size: 10px 2em
.c
size: 1px 2em
编译为:
.a,
.b {
width: 10px;
}
.a {
height: 20px;
}
.b,
.c {
height: 2em;
}
.c {
width: 1px;
}
四、+prefix-classes()
添加前缀
+prefix-classes()
用于给包含的类添加指定的前缀。
基础语法
+prefix-classes(prefix)
// 包含的样式规则
prefix
:前缀字符串,用于给类选择器添加前缀。不能修改 ID 选择器。
基础示例
例如:
+prefix-classes('foo-')
.bar
width: 10px
.baz
width: 20px
编译为:
.foo-bar {
width: 10px;
}
.foo-baz {
width: 20px;
}
嵌套类名示例
+prefix-classes('foo-')
.bar
width: 10px
.baz
width: 20px
编译为:
.foo-bar {
width: 10px;
}
.foo-bar .foo-baz {
width: 20px;
}
多级嵌套示例
+prefix-classes('lib-')
.component
margin: 10px
+prefix-classes('inner-')
.part
color: blue
编译为:
.lib-component {
margin: 10px;
}
.lib-inner-part {
color: #00f;
}
五、lookup()
查找变量
lookup()
是 Stylus 中的一个内置函数,用于查找变量的值。如果变量未定义,则返回 null
。
基础语法
lookup(name)
name
:要查找的变量名。
基础示例
当你需要获取具有动态生成名称的变量的值时很有用:
font-size-1 = 10px
font-size-2 = 20px
font-size-3 = 30px
for i in 1..3
.text-{i}
font-size: lookup('font-size-' + i)
编译为:
.text-1 {
font-size: 10px;
}
.text-2 {
font-size: 20px;
}
.text-3 {
font-size: 30px;
}
六、define()
创建或覆盖变量
允许使用给定的 name
创建或覆盖变量,以字符串形式传递到当前作用域(如果 global
为 true,则为全局作用域)。如果变量不存在,则创建一个新变量;如果变量已存在,则覆盖其值。
基础语法
define(name, value, global = false)
name
:变量名。value
:变量的值,可以是任何有效的 Stylus 表达式。global
:可选参数,指定变量是否为全局变量,默认为 false。
基础示例
prefix = 'border'
border = { color: #000, length: 1px, style: solid }
for prop, val in border
define(prefix + '-' + prop, val)
body
border: border-length border-style border-color
编译为:
body {
border: 1px solid #000;
}
七、operate()
操作函数
operate()
是 Stylus 中的一个内置函数,用于执行给定的二元操作。
基础语法
operate(op, left, right)
op
:操作符,可以是任何有效的 Stylus 操作符,例如+
、-
、*
、/
等。left
:左操作数,可以是任何有效的 Stylus 表达式。right
:右操作数,可以是任何有效的 Stylus 表达式。
基础示例
op = '+'
operate(op, 15, 5) // => 20
八、selector()
输出当前选择器字符串
selector() 函数返回当前上下文的选择器字符串,包括所有父级选择器。
.nav
.item
&:after
content: selector() // 输出当前选择器
.foo
&:hover
content: selector()
编译为:
.nav .item:after {
content: ".nav .item:after";
}
.foo:hover {
content: ".foo:hover";
}
九、selector-exists()
选择器是否存在
selector-exists() 函数用于检查给定的选择器是否存在于当前上下文。
基础语法
selector-exists(selector)
selector
:要检查的选择器,可以是任何有效的 Stylus 选择器。
基础示例
.foo
color red
a
font-size 12px
selector-exists('.foo') // true
selector-exists('.foo a') // true
selector-exists('.foo li') // false
selector-exists('.bar') // false
此方法不考虑当前上下文含义:
.foo
color red
a
font-size 12px
selector-exists('a') // false
selector-exists(selector() + ' a') // true
十、opposite-position()
输出反方向
返回给定位置或者方向的的相反值。
基础语法
opposite-position(position)
position
:位置或者方向,可以是任何有效的 Stylus 位置或者方向。
基础示例
opposite-position(right) // => left
opposite-position(top left) // => bottom right
opposite-position('top' 'left') // => bottom right
十一、image-size()
图片宽、高
image-size()
是 Stylus 的一个内置函数,用于获取图片的宽度和高度,而不需要实际加载图片到页面中。
基础语法
width, height = image-size(path)
path
:图片的路径,可以是相对路径或绝对路径。
基础示例
width(img)
return image-size(img)[0] // 20px
height(img)
return image-size(img)[1] // 30px
image-size('tux.png') // => 405px 250px
image-size('tux.png')[0] == width('tux.png') // => true
十二、embedurl()
内嵌图片
以 url()
字面量形式嵌入代码中,并使用 encoding
进行编码。
(可用编码:base64
(默认)和 utf8
)。
基础语法
embedurl(path, encoding = 'base64')
path
:图片的路径,可以是相对路径或绝对路径。encoding
:可选参数,指定图片编码方式,默认为base64
,还可以选择utf8
。
基础示例
background: embedurl('logo.png')
// => background: url("data:image/png;base64,…")
background: embedurl('logo.svg', 'utf8')
// => background: url("data:image/svg+xml;charset=utf-8,…")
十三、add-property()
添加属性
add-property()
是 Stylus 中的一个内置函数,用于给指定的块添加一个新的属性。
基础语法
add-property(name, value)
name
:要添加的属性名,可以是任何有效的 Stylus 表达式。value
:要添加的属性值,可以是任何有效的 Stylus 表达式。
基础示例
something()
add-property('bar', 1 2 3)
s('bar')
body
foo: something()
编译为:
body {
bar: 1 2 3;
foo: bar;
}
接下来的例子中:current-property
局部变量开始发挥作用。该变量自动可供函数体使用,并包含具有当前属性名称和值的表达式。
例如,如果我们使用 p()
检查这个局部变量,我们会得到以下结果:
p(current-property)
// => "foo" (foo __CALL__ bar baz)
p(current-property[0])
// => "foo"
p(current-property[1])
// => foo __CALL__ bar baz
使用 current-property
,我们可以进一步扩展示例,并使用新值和条件复制属性,以确保该函数仅在属性值中使用。
something(n)
if current-property
add-property(current-property[0], s('-webkit-something(%s)', n))
add-property(current-property[0], s('-moz-something(%s)', n))
s('something(%s)', n)
else
error('something() must be used within a property')
body {
foo: something(15px) bar;
}
编译为:
body {
foo: -webkit-something(15px);
foo: -moz-something(15px);
foo: something(15px) bar;
}
如果你在上面的示例中注意到,bar
仅在初始调用中出现,因为我们返回了 something(15px)
,所以它在表达式中保留在适当的位置,但是其他表达式不会考虑表达式的其余部分。
下面我们更健壮的解决方案定义了一个名为 replace()
的函数,该函数克隆表达式以防止突变,将表达式的字符串值替换为另一个表达式,然后返回克隆的表达式。然后我们继续替换表达式中的 __CALL__
,它表示对 something()
的循环调用。
replace(expr, str, val)
expr = clone(expr)
for e, i in expr
if str == e
expr[i] = val
expr
something(n)
if current-property
val = current-property[1]
webkit = replace(val, '__CALL__', s('-webkit-something(%s)', n))
moz = replace(val, '__CALL__', s('-moz-something(%s)', n))
add-property(current-property[0], webkit)
add-property(current-property[0], moz)
s('something(%s)', n)
else
error('something() must be used within a property')
body
foo: something(5px) bar baz
编译为:
body {
foo: -webkit-something(5px) bar baz;
foo: -moz-something(5px) bar baz;
foo: something(5px) bar baz;
}
现在,我们的实现在调用它的属性和调用的位置方面都是完全透明的。
这个强大的概念有助于浏览器对函数调用(例如渐变)的透明支持。
更新日志
e7112
-1于