夜猫子的知识栈 夜猫子的知识栈
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

夜猫子

前端练习生
首页
  • 前端文章

    • JavaScript
  • 学习笔记

    • 《JavaScript教程》
    • 《Web Api》
    • 《ES6教程》
    • 《Vue》
    • 《React》
    • 《TypeScript》
    • 《Git》
    • 《Uniapp》
    • 小程序笔记
    • 《Electron》
    • JS设计模式总结
  • 《前端架构》

    • 《微前端》
    • 《权限控制》
    • monorepo
  • 全栈项目

    • 任务管理日历
    • 无代码平台
    • 图书管理系统
  • HTML
  • CSS
  • Nodejs
  • Midway
  • Nest
  • MySql
  • 其他
  • 技术文档
  • GitHub技巧
  • 博客搭建
  • Ajax
  • Vite
  • Vitest
  • Nuxt
  • UI库文章
  • Docker
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术文档

    • Git使用手册
    • Markdown使用教程
    • npm常用命令
    • yarn基本命令
    • npm packageJson属性详解
    • yaml语言教程
    • Stylus预处理语言
      • 父选择器
      • 选择器链
        • 局部引用
        • 向上索引
      • 插值函数
        • 模板语法
        • 迭代插值 for in
      • 变量
      • 属性查找
      • 运算符
        • 运算符优先级
        • 一元运算符
        • 二元运算符
        • 下标运算符 []
        • 范围运算符 .. ...
        • 数学运算符
        • 真值运算符
        • 逻辑运算符 && ||
        • 存在运算符:in
        • 条件赋值运算符:?= :=
        • 类型检查运算符:is a
        • 变量定义检查运算符:is defined
        • 三元运算符
        • 添加单位 unit()
      • 函数
        • 返回值
        • 默认参数
        • 命名参数
        • 返回多个值
        • 条件
        • 函数作为变量使用
        • 匿名函数
        • 参数
        • Hash 实例
      • 关键字参数
      • 迭代器
        • 后置表达式
      • 内置函数
        • alpha(color, value)
        • rgba(color | r,g,b,a)
        • push(expr, args…)
        • pop(expr)
        • shift(expr)
        • unshift(expr, args…)
        • index(list, value)
        • keys(pairs)
        • values(pairs)
        • length([expr])
        • typeof(node)
        • unit(val[, type])
        • percentage(num)
        • sum(nums)
        • avg(nums)
        • join(delim, vals…)
        • split(delim, val)
        • substr(val, start, length)
        • slice(val, start[, end])
        • lookup(name)
        • warn(msg)
        • error(msg)
    • Less预处理语言
    • Sass预处理语言
    • PWA运用
    • 富文本编辑器Ueditor
    • 发布npm
    • 构建一个TS的npm包
    • tsup打包工具
    • leaflet地图框架
    • pdfjs-dist使用
    • xlsx插件使用
    • changesets
    • release-it
    • mathjs
  • GitHub技巧

  • 博客搭建

  • Ajax

  • Vite

  • Vitest

  • Nuxt

  • UI库文章

  • Docker

  • 技术
  • 技术文档
夜猫子
2022-12-16
目录

Stylus预处理语言

# Stylus 预处理语言

Stylus 结合了 scss 和 less 语言的特点,有着比 less 语言更强大的功能,同时有着比 scss 更简单的配置(无需安装 sass-node 这样的支持),支持省去花括号和分号的写法。

只需安装 node.js,然后,在命令行中执行如下指令:

$ npm install stylus -g
1

# 父选择器

& 符号代表父级选择器。

textarea
input
  color #A7A7A7
  &:hover
    color #000
1
2
3
4
5

编译为:

textarea,
input {
  color: #a7a7a7;
}
textarea:hover,
input:hover {
  color: #000;
}
1
2
3
4
5
6
7
8

如果需要在选择器中单纯地使用&符,不使用其父级引用的功能,可以通过转义符\来转义:

.foo[title*='\&']
// => .foo[title*='&']
1
2

# 选择器链

^[N] 表示选择器链的选取,^[0] 表示第一级选择器,^[1] 表示第二级选择器,并以此类推。

.foo
  &__bar
    width: 10px

    ^[0]:hover &
      width: 20px
1
2
3
4
5
6

编译为

.foo__bar {
  width: 10px;
}
.foo:hover .foo__bar {
  width: 20px;
}
1
2
3
4
5
6

当 N 为负数时表示从结尾开始索引。所以^[-1]将给出链中&之前的最后一个选择器:

.foo
  &__bar // ^[-1] 表示这一级的选择器
    &_baz
      width: 10px

      ^[-1]:hover &
        width: 20px
1
2
3
4
5
6
7

编译为

.foo__bar_baz {
  width: 10px;
}
.foo__bar:hover .foo__bar_baz {
  width: 20px;
}
1
2
3
4
5
6

# 局部引用

之前的选择链都是从根级到指定的层级,但如果是要选择指定范围的选择器链,可以使用 ^[N..M], 其表示选择从 N 到 M 范围的选择器链。

.foo
  & .bar
    width: 10px

    ^[0]:hover ^[1..-1]
      width: 20px
1
2
3
4
5
6

编译为

.foo .bar {
  width: 10px;
}
.foo:hover .bar {
  width: 20px;
}
1
2
3
4
5
6

# 向上索引

使用 ../../ 语法可以从当前链向上索引。

.foo
  .bar
    width: 10px

    &,
    ../ .baz
      height: 10px
1
2
3
4
5
6
7

编译为

.foo .bar {
  width: 10px;
}
.foo .bar,
.foo .baz {
  height: 10px;
}
1
2
3
4
5
6
7

# 插值函数

当属性值未知时可以使用函数选择器占位属性

pad(n)
  margin (- n)

body
  pad(5px)
  
// 编译为  

body {  margin: -5px;}
1
2
3
4
5
6
7
8
9

# 模板语法

使用 {any} 语法可以解析参数。甚至可以嵌套传参。

vendor(prop1,prop2,args)
	{prop1}-top:args
    {prop2}-top:args

MarginAndPadding()
    vendor('margin','padding',arguments)

button
    MarginAndPadding 4px

// 编译为

button{margin-top:4px;padding-top:4px}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 迭代插值 for in

table
  for row in 1 2 3 4 5
    tr:nth-child({row})
      height: 10px * row
1
2
3
4

编译为

table tr:nth-child(1) {
  height: 10px;
}
table tr:nth-child(2) {
  height: 20px;
}
table tr:nth-child(3) {
  height: 30px;
}
table tr:nth-child(4) {
  height: 40px;
}
table tr:nth-child(5) {
  height: 50px;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 变量

$fontSize = 14px
$fontStack = "Lucida Grande", Arial, sans-serif 

body
  font $fontSize $fontStack 

//编译为:
body {
  font: 14px "Lucida Grande", Arial, sans-serif;
}
1
2
3
4
5
6
7
8
9
10

变量类型

$var = "Lucida Grande", Arial, sans-serif  // 基础类型
$arr = width height margin padding // 数组类型
$keyValue = (width 15px) // 键值对类型
$list = (width 15px) (height 15px) (margin 15px) (padding 15px) // 复合类型
1
2
3
4

# 属性查找

一个很棒的功能,可以通过前置 @ 符来访问该属性对应值。

属性查找会从当前选择器往上冒泡,查找堆栈直到被发现对应属性。

 #logo
   position: absolute
   top: 50%
   left: 50%
   width: 150px
   height: 80px
   margin-left: -(@width / 2) // @width=150px
   margin-top: -(@height / 2)// @height=80px
1
2
3
4
5
6
7
8

# 运算符

# 运算符优先级

 .
 []
 ! ~ + -
 is defined
 ** * / %
 + -
 ... ..
 <= >= < >
 in
 == is != is not isnt
 is a
 && and || or
 ?:
 = := ?= += -= *= /= %=
 not
 if unless
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 一元运算符

可用的一元运算符包括 !、not、-、+ 和 ~。

!0
// => true

!!0
// => false

!1
// => false

!!5px
// => true

-5px
// => -5px

--5px
// => 5px

not true
// => false

not not true
// => true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 二元运算符

# 下标运算符 []

 list = 1 2 3
 list[0]
 // => 1

 list[-1]
 // => 3
1
2
3
4
5
6

# 范围运算符 .. ...

 1..5
 // => 1 2 3 4 5

 1...5
 // => 1 2 3 4

 5..1
 // => 5 4 3 2 1
1
2
3
4
5
6
7
8

# 数学运算符

包括 加减乘除,累加累减累乘累除,指数运算符(**),相等与关系运算:(==、 !=、 >=、 <=、 >、<)

# 真值运算符

# 逻辑运算符 && ||

5 && 3
// => 3

0 || 5
// => 5

0 && 5
// => 0

#fff is a 'rgba' and 15 is a 'unit'
// => true
1
2
3
4
5
6
7
8
9
10
11

# 存在运算符:in

此运算符用于检查 左侧 操作数是否存在于 右侧 表达式中。

简单示例:

  nums = 1 2 3
  1 in nums
  // => true

  5 in nums
  // => false
  
  words = foo bar baz
  bar in words
  // => true

  HEY in words
  // => false
1
2
3
4
5
6
7
8
9
10
11
12
13

# 条件赋值运算符:?= :=

条件赋值运算符 ?= (别名 :=)允许我们定义变量而不删除旧值(如果存在的话)。

例如,以下内容是等效的:

color := white
color ?= white
color = color is defined ? color : white
1
2
3

使用 ?= 时,第二次的赋值就会失败

color = white
color ?= black

color
// => white
1
2
3
4
5

# 类型检查运算符:is a

15 is a 'unit'
// => true

#fff is a 'rgba'
// => true

#fff is a 'color'
// => true

15 is a 'rgba'
// => false
1
2
3
4
5
6
7
8
9
10
11

# 变量定义检查运算符:is defined

foo is defined
// => false

foo = 15px
foo is defined
// => true

#fff is defined
// => 'invalid "is defined" check on non-variable #fff'
1
2
3
4
5
6
7
8
9

# 三元运算符

num = 15
num ? unit(num, 'px') : 20px
// => 15px
1
2
3

# 添加单位 unit()

其中内置函数 unit() 的简洁替代写法为

body
  n = 5
  foo: (n)em
  foo: (n)%
  foo: (n + 5)%
  foo: (n * 5)px
  foo: unit(n + 5, '%')
  foo: unit(5 + 180 / 2, deg)
1
2
3
4
5
6
7
8

# 函数

类似于 less 和 scss 中的混入,但是更加强大,可以返回返回值。

# 返回值

add(a, b)
  a + b

body 
  padding add(10px, 5)
  
// 结果为
body {
   padding: 15px;
 }
1
2
3
4
5
6
7
8
9
10

# 默认参数

 add(a, b = a)
   a + b

 add(10, 5)
 // => 15
 
 add(10)
 // => 20
1
2
3
4
5
6
7
8

注意: 因为参数默认是赋值,因此我们可以使用函数调用作为默认值:

 add(a, b = unit(a, px))
   a + b
1
2

# 命名参数

函数可以接受命名参数。这可以免去记忆参数顺序的麻烦,或者说是提供了代码的可读性。

例如:

subtract(a, b)
  a - b

subtract(b: 10, a: 25)
1
2
3
4

# 返回多个值

 sizes()
     15px 10px

 sizes()[0]
   // => 15px
1
2
3
4
5
  swap(a, b)
    (b a)
  // 或
  swap(a, b)
    return b a
1
2
3
4
5

# 条件

compare(a, b)
  if a > b
    higher
  else if a < b
    lower
  else
    equal
1
2
3
4
5
6
7

用法:

compare(5, 2)
// => higher

compare(1, 5)
// => lower

compare(10, 10)
// => equal
1
2
3
4
5
6
7
8

# 函数作为变量使用

与为函数起 “别名” 一样,我们可以将函数作为参数传递。如下, invoke() 函数能够接收一个函数作为参数,因此我们可以将 add() 或 sub() 函数作为参数传递给 invoke()。

add(a, b)
  a + b

sub(a, b)
  a - b

invoke(a, b, fn)
  fn(a, b)

body
  padding unit(invoke(5, 10, add),'px')
  padding unit(invoke(5, 10, sub),'px')
1
2
3
4
5
6
7
8
9
10
11
12

生成:

body {
  padding: 15px;
  padding: -5px;
}
1
2
3
4

# 匿名函数

利用 @(){} 语法可以在需要的地方使用匿名函数。下面展示了如何利用匿名函数创建一个自定义的 sort() 函数:

sort(list,fn=null)
    if fn==null
      fn=@(a,b){ // 默认匿名函数函数
        a > b
      }
      
    for $i in 1..length(list)-1
		for $j in 0..$i-1
            if fn(list[$i],list[$j])
                $temp = list[$i]
       		    list[$i] = list[$j]
                list[$j] = $temp
     return list
     
sort('e' 'c' 'f' 'a' 'b' 'd')
  // => 'a' 'b' 'c' 'd' 'e' 'f'

sort(5 3 6 1 2 4, @(a, b){
    a < b
})
  // => 6 5 4 3 2 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 参数

arguments 是所有函数体都能够访问的局部变量,包含了传递过来的所有参数。

例如:

 sum()
   n = 0
   for num in arguments
     n = n + num

 sum(1,2,3,4,5)
 // => 15
1
2
3
4
5
6
7

# Hash 实例

下面我们定义了 get(hash, key) 函数,返回 key 的值或 null。我们遍历 hash 中的每个键值对(pair),如果键(key)相匹配则返回对应的值。

 get(hash, key)
   for pair in hash
     if pair[0] == key
        return pair[1] 
1
2
3
4

如下所示,语言内置的函数功能和 Stylus 表达式相结合,能够提供强大的灵活性:

  hash = (one 1) (two 2) (three 3)
  
  get(hash, two)
  // => 2

  get(hash, three)
  // => 3

  get(hash, something)
  // => null
1
2
3
4
5
6
7
8
9
10

# 关键字参数

Stylus 支持关键字参数或 “kwargs”。这样就能够通过其关联的参数名来引用参数。

以下示例在功能上是等价的。 然而,我们可以 在参数列表中的任何位置放置关键字参数。 未设置关键字的参数将被用来填充其余尚未填充的参数。

  body {
    color: rgba(255, 200, 100, 0.5);
    color: rgba(red: 255, green: 200, blue: 100, alpha: 0.5);
    color: rgba(alpha: 0.5, blue: 100, red: 255, 200);
    color: rgba(alpha: 0.5, blue: 100, 255, 200);
  }
1
2
3
4
5
6

# 迭代器

$attrs=width height
body
  for $attr in $attrs
  	for num in (1..5)
    	$attr unit(num,'px')
1
2
3
4
5

生成:

body {
  width: 1px;
  width: 2px;
  width: 3px;
  width: 4px;
  width: 5px;
  height: 1px;
  height: 2px;
  height: 3px;
  height: 4px;
  height: 5px;
}
1
2
3
4
5
6
7
8
9
10
11
12

# 后置表达式

就跟 if / unless 可以利用后置表达式(post-statement)一样,for 也可以。如下是一些使用后置表达式语法的例子:

   sum(nums)
     sum = 0
     sum += n for n in nums


   join(delim, args)
     buf = ''
     buf += i ? delim + arg : arg for arg, i in args
1
2
3
4
5
6
7
8

我们还可以从循环中 return (返回),下面就是一个实例,当 n % 2 == 0 的值为 true 时就返回数值。

 first-even(nums)
   return n if n % 2 == 0 for n in nums

 first-even(1 3 5 5 6 3 2)
 // => 6
1
2
3
4
5

# 内置函数

stylus 提供了许多强大的内置函数 (opens new window)来方便使用。

几个实用函数:

# alpha(color, value)

alpha(#fff)
// => 1

alpha(rgba(0,0,0,0.3))
// => 0.3

alpha(#fff, 0.5)
// => rgba(255,255,255,0.5)
1
2
3
4
5
6
7
8

# rgba(color | r,g,b,a)

rgba(255,0,0,0.5)
// => rgba(255,0,0,0.5)

rgba(255,0,0,1)
// => #ff0000

rgba(#ffcc00, 0.5)
// rgba(255,204,0,0.5)
1
2
3
4
5
6
7
8

# push(expr, args…)

nums = 1 2
push(nums, 3, 4, 5)

nums
// => 1 2 3 4 5
1
2
3
4
5

# pop(expr)

nums = 4 5 3 2 1
num = pop(nums)

nums
// => 4 5 3 2
num
// => 1
1
2
3
4
5
6
7

# shift(expr)

nums = 4 5 3 2 1
num = shift(nums)

nums
// => 5 3 2 1
num
// => 4
1
2
3
4
5
6
7

# unshift(expr, args…)

nums = 4 5
unshift(nums, 3, 2, 1)

nums
// => 1 2 3 4 5
1
2
3
4
5

# index(list, value)

list = 1 2 3

index(list, 2)
// => 1

index(1px solid red, red)
// => 2
1
2
3
4
5
6
7

# keys(pairs)

pairs = (one 1) (two 2) (three 3)
keys(pairs)
// => one two three
1
2
3

# values(pairs)

pairs = (one 1) (two 2) (three 3)
values(pairs)
// => 1 2 3
1
2
3

# length([expr])

length((1 2 3 4))
// => 4

length(1 2 3)
// => 3

length(1)
// => 1

length()
// => 0
1
2
3
4
5
6
7
8
9
10
11

# typeof(node)

type(12)
// => 'unit'

typeof(12)
// => 'unit'

typeof(#fff)
// => 'rgba'

type-of(#fff)
// => 'rgba'
1
2
3
4
5
6
7
8
9
10
11

# unit(val[, type])

unit(10)
// => ''

unit(15in)
// => 'in'

unit(15%, 'px')
// => 15px

unit(15%, px)
// => 15px
1
2
3
4
5
6
7
8
9
10
11

# percentage(num)

percentage(.5)
// => 50%

percentage(4 / 100)
// => 4%
1
2
3
4
5

# sum(nums)

sum(1 2 3)
// => 6
1
2

# avg(nums)

avg(1 2 3)
// => 2
1
2

# join(delim, vals…)

join(' ', 1 2 3)
// => "1 2 3"

join(',', 1 2 3)
// => "1,2,3"

join(', ', foo bar baz)
// => "foo, bar, baz"

join(', ', foo, bar, baz)
// => "foo, bar, baz"

join(', ', 1 2, 3 4, 5 6)
// => "1 2, 3 4, 5 6"
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# split(delim, val)

split(_, bar1_bar2_bar3)
// => bar1 bar2 bar3

split(_, 'bar1_bar2_bar3')
// => 'bar1' 'bar2' 'bar3'
1
2
3
4
5

# substr(val, start, length)

The substr() method returns the characters in a string beginning at the specified location through the specified number of characters.

substr(ident, 1, 2)
// => de

substr('string', 1, 2)
// => 'tr'

val = dredd
substr(substr(val, 1), 0, 3)
// => #f00
1
2
3
4
5
6
7
8
9

# slice(val, start[, end])

slice('lorem' 'ipsum' 'dolor', 1, 2)
slice('lorem' 'ipsum' 'dolor', 1, -1)
// => 'ipsum'

slice('lorem ipsum', 1, 5)
// => 'orem'
slice(rredd, 1, -1)
// => #f00

slice(1px solid black, 1)
// => solid #000
1
2
3
4
5
6
7
8
9
10
11

# lookup(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)
1
2
3
4
5
6
7

编译为

.text-1 {
  font-size: 10px;
}
.text-2 {
  font-size: 20px;
}
.text-3 {
  font-size: 30px;
}
1
2
3
4
5
6
7
8
9

# warn(msg)

warn("oh noes!")
1

# error(msg)

add(a, b)
  unless a is a 'unit' and b is a 'unit'
    error('add() expects units')
  a + b
1
2
3
4
编辑 (opens new window)
上次更新: 2023/7/11 18:57:41
yaml语言教程
Less预处理语言

← yaml语言教程 Less预处理语言→

最近更新
01
IoC 解决了什么痛点问题?
03-10
02
如何调试 Nest 项目
03-10
03
Provider注入对象
03-10
更多文章>
Copyright © 2019-2025 Study | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式