过滤器与表达式
NornJ
模板的插值变量中可以使用过滤器
来对数据进行一些运算、过滤操作,语法和Vue 2.0
中的过滤器较为类似。
另外,模板的插值变量中也支持一些常用的js表达式
,如{{ [1, 2][0] * 3 }}
。然而表达式语法实际上是过滤器的语法糖写法,这是NornJ
与其他模板对比的一个很有特色的地方。故NornJ
中可以支持js语法
中并不支持的运算符如..
、**
等,且还可以自由扩展出更多的新运算符。
过滤器
过滤器
语法为{插值变量 | 过滤器1 | 过滤器2...}
,如使用多个过滤器则会按顺序依次执行,如下所示:
//每个过滤器都是一个函数,使用nj.registerFilter方法全局注册
nj.registerFilter('2x', num => num * 2);
console.log(nj`<div>{{100 | +(50) | 2x}}</div>`()); //输出<div>300</div>
- 可以一次定义多个全局过滤器:
nj.registerFilter({
trim: obj => obj.trim(),
replace: obj => obj.replace(/id/g, 'test1')
});
局部过滤器
- 还可以使用局部过滤器,将过滤器函数定义为插值变量即可:
nj`<div>{{1 | test}}</div>`({
test: value => value + '_test'
});
过滤器参数
- 过滤器也可以添加参数,语法为
{插值变量 | 过滤器1(参数1,参数2...) | 过滤器2(参数1,参数2...)...}
。在过滤器方法中第一个参数是当前传入的数据;从第二个参数开始依次为这些模板中传入的参数,如下所示:
nj.registerFilter('test', (obj, p1, p2) => {
console.log(obj); //输出test
console.log(p1); //输出1,过滤器参数的语法规则与插值语法相同
console.log(p2); //输出2,过滤器参数也可以传入插值变量动态求值
return obj;
});
nj`<div>{{data | test(1, arg2)}}</div>`({
data: 'test',
arg2: 2
});
- 在过滤器的参数中也支持嵌套过滤器:
<#if {{i | filter1(j | filter2(k | filter3))}}>...</#if>
- 有参数的过滤器可以省略
|
符号,但是过滤器名称前必须有空格(至少一个空格或换行,除了几种特殊的过滤器
,目前有.
、_
、#
三个),例如:
<#if {{i >=(0) ||(i <=(-10))}}>...</#if>
函数型过滤器
- 还可以直接以函数调用的方式来使用过滤器,称为
函数型过滤器
。语法为将过滤器名称当做函数调用即可,例如:
{{ bool(1) }}
和
{{ 1 | bool }}
是等价的,结果都为true
。
注意:
函数型过滤器
的前面可以不加空格。
过滤器内部的options参数
- 注册过滤器函数的最后一个参数即为options参数,它是一个对象类型。从options中可以获取到模板内部的一些值,主要用于实现一些复杂的模板扩展功能,如下所示:
nj.registerFilter('test', function(val, options) {
const ctx = options.context;
console.log(ctx.getData('id')); //输出100
console.log(ctx.data[0]); //输出1
console.log(ctx.parent.data[0]); //输出{ list: [1] }
console.log(ctx.index); //输出0
return val;
});
nj`
<#each {{list}}>
{{@index | test}}
</#each>
`({ list: [1] }, { id: 100 });
options参数列表(更多参数及细节待补充):
参数名称 | 类型 | 作用 |
---|---|---|
_njOpts | Object | 主要用在过滤器参数数量不固定时,用来判断是否为options参数 |
context | Object | 模板内部的上下文数据 |
lastValue | Any | 上一个的上一个过滤器的结果值,在过滤器函数内使用call及apply时可能会用到 |
表达式
过滤器
只传一个参数时还支持省略扩号,这样就可以用类似js表达式
的格式来编写,例如:
{{i >=(0) ||(i <=(-10))}}
就可以改写为:
{{i >= 0 || (i <= -10)}} //注意">="、"<="等符号两侧都要有至少一个空格
这种使用过滤器的方式即为NornJ模板的表达式语法
,实质上是编写过滤器的一种语法糖,规则为捕获过滤器名称后面的第一个变量(包含链式的变量)
,正确的用法举例如下:
{{1 + 2 * 3}} //结果为9
{{1 + (2 * 3)}} //结果为7
{{a + b.c}}
{{a + b.c.trim() + d.e}}
{{ { a: 1, b: 2 }.b * 100 }} //结果为200
{{ [1, 2, 3][0] + 100 }} //结果为101
NornJ
表达式中的运算符暂时没有优先级的概念,它会从左至右执行各种运算,并使用括号控制优先级:
{{1 + 2 * 3}} //结果为9
{{1 + (2 * 3)}} //结果为7
预计在
NornJ
未来的版本中会加入运算符优先级。
- 运算符两侧至少要有一个空格。请注意,以下语法都是错误的:
{{1+2 * 3}} //语法错误,"+"的两端必须有空格
{{a -b.c}} //语法错误,"-"的两端必须有空格
{{a+ b.c.trim()+d.e}} //语法错误,"+"的两端必须有空格
使用上述错误的语法时,NornJ
会在控制台发出相应的警告信息。
预计在
NornJ
未来的版本中会允许运算符两侧没有空格。
内置过滤器
- 表达式中的部分运算符及字面量(如
a.b
、{ a: 1 }
、[1, 2]
等)实际上都是过滤器的语法糖写法,具体请看内置过滤器。