---
title: 参数解析
---
## 访问原始参数
在 [注册过滤器和标签][register-tags] 中提到,可以通过 `tagToken.args` 来得到标签的原始参数字符串。例如:
```javascript
// Usage: {% random foo bar coo %}
// Output: "foo", "bar" or "coo"
engine.registerTag('random', {
parse(tagToken) {
// tagToken.args === "foo bar coo"
this.items = tagToken.args.split(' ')
},
render(context, emitter) {
// get a random index
const index = Math.floor(this.items.length * Math.random())
// output that item
emitter.write(this.items[index])
}
})
```
见这个 JSFiddle:。
## 解析参数的值
除了静态的参数字符串之外,我们更希望把动态的值传递给标签。LiquidJS 中的值可以是字面量(字符串、数字等,也可以是当前上下文的变量。
下面是修改过的模板,也包含三个值用来随机。但它们表示的是值而不是静态的字符串。第一个是字符串字面量,第二个是标识符(表示变量),第三个是属性访问表达式,包含两个标识符。
```liquid
{% random "foo" bar obj.coo %}
```
解析这么多种情况会很麻烦,但 LiquidJS 提供了 [Tokenizer][Tokenizer] 类来处理这种情况。
```javascript
const { Liquid, Tokenizer, evalToken } = require('liquidjs')
engine.registerTag('random', {
parse(tagToken) {
const tokenizer = new Tokenizer(tagToken.args)
this.items = []
while (!tokenizer.end()) {
// here readValue() returns a LiteralToken or PropertyAccessToken
this.items.push(tokenizer.readValue())
}
},
* render(context, emitter) {
const index = Math.floor(this.items.length * Math.random())
const token = this.items[index]
// in LiquidJS, we use yield to wait for async call
const value = yield evalToken(token, context)
emitter.write(value)
}
})
```
用上下文 `{ bar: "bar", obj: { coo: "coo" } }` 来调用这个标签可以得到上第一个例子一样的效果。见这个 JSFiddle:.
{% note info 异步和 Promise %}
在 LiquidJS 里异步用生成器实现,这样同样一份标签的实现也可以用于同步的 API 比如 `renderSync()`,`parseAndRenderSync()`,`renderFileSync()`。如果要在标签实现里等待 Promise,只需要把 `await somePromise` 换成 `yield somePromise`,并保留 `* render()` 不要改成 `async render()`。更多细节请参考 Sync and Async。
{% endnote %}
## 把键值对解析为命名参数
当参数很多时或者有可选参数时,使用命名参数语法会很方便。这时参数由无序的键值对构成,LiquidJS 中的 [Hash][Hash] 类就是来处理这种情况的。
```liquid
{% random from:2, to:max %}
```
上面的例子用来产生 [2, max] 范围内的随机数。我们要用 `Hash` 来解析 `from` 和 `to` 参数。
```javascript
const { Liquid, Hash } = require('liquidjs')
engine.registerTag('random', {
parse(tagToken) {
// 解析参数结果,存到 `this.args` 里
this.args = new Hash(tagToken.args)
},
* render(context, emitter) {
// 在当前 `context` 下计算参数的值
const {from, to} = yield this.args.render(context)
const length = to - from + 1
const value = from + Math.floor(length * Math.random())
emitter.write(value)
}
})
```
在 `{ max: 10 }` 上下文上渲染 `{% random from:2, to:max %}` 将会得到 [2, 10] 范围内的随机数。见这个 JSFiddle:。
[register-tags]: /tutorials/register-filters-tags.html
[Tokenizer]: /api/classes/Tokenizer.html
[Hash]: /api/classes/Hash.html