> For the complete documentation index, see [llms.txt](https://seek.gitbook.io/acr/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://seek.gitbook.io/acr/shi-yong.md).

# 使用

## 概念

#### 验证链

每个 `acr.string()` 或者 `acr.number()` 这样的类型声明后面返回的都是一个 `chain`我们称之为 **验证链** 。它就像一个链条，声明了我们对这个字段的数据要进行的种种验证。而数据会在这个链条上依次验证，直到全部通过或者某个验证没有通过为止（前面的验证没有通过，后面的验证不会继续执行）。

```javascript
await acr.string().min(2).max(5).equal('bar').validate('foobar');
```

在上面的例子中，验证链上分别有 3 个规则（`min`, `max`, `equal`），当到达第二个(`max`)时，`foobar` 字符数大于了 5，因此失败，而 `equal` 验证则不会执行。

## 数据验证

```javascript
await acr.validate({
    foo: 'bar'
}, {
    foo: acr.string().min(2).max(5).equal('bar')
});
```

数据验证方法接受两个参数：

`data`: 用于验证的数据

`rules`: 验证规则

比如在 egg 中（推荐在 egg 中使用 [egg-acr](https://github.com/seekcx/egg-acr) 插件），我们可以将 ctx 上的表单数据进行验证：

```javascript
await acr.validate(ctx.request.body, {
    // rules
});
```

## 默认值

一些可选的参数常常拥有一个默认值，虽然实现并不复杂，但这无疑增加了代码的复杂程度，也不够优雅，因此，从 1.2.0 开始 acr 支持设置默认值。

```javascript
const [ foo ] = await acr.validate({}, {
  foo: acr.string().default('bar'),
});

foo; // 'bar';
```

有时候，可能需要复杂的计算才能得出默认值：

```javascript
const [ foo ] = await acr.validate({
  bax: 123,
}, {
  foo: acr.string().default((data, context) => {
    return data['bax'] === 123 ? 'bar' : 456;
  }),
});

foo; // 'bar';
```

## 数据转换

很多情况下，我们验证的数据就是即将使用的数据。为此，acr 提供了一个便捷的方式来获取数据和转换数据。

```javascript
const { nickname, password } = await acr.validate({
    nickname: 'seek',
    password: 'secret'
}, {
    nickname: acr.string().max(12).transform(value => value + 'cx')
    password: acr.string({ 
            transform: value => value + 'salt'
        })
        .max(32);
});

console.log(nickname); // seekcx 
console.log(password); // secretsalt
```

转换函数的参数是一个 `(value: any): Promise<any>` 类型的闭包，闭包会得到一个 `value`，返回值会被作为最终数据。

上面的例子展示了两种对数据进行转换的方式：

第一种是在验证链上使用 `transform` ，第二种是在声明时使用配置的方式。除此之外，还可以在 配置 中声明 chians 来声明默认的转换，详细可以参考 [配置](/acr/config.md)。

## 参数命名

有时候的验证的错误提示在某些场景显得不那么友好。比如：

```javascript
await acr.validate({
    nickname: 'foobar',
}, {
    nickname: acr.string().max(5),
});
```

这种情况，大多数验证组件都会提示：`nickname must be at most 5 characters` 。这看起来似乎没有什么不对。但当我们把语言环境切换到 中文 时，这个错误会变为 `nickname不能超过 5 个字符`。这对用户来说十分奇怪，因为用户并不知道这个 `nickname` 什么意思。

为了解决这个问题，acr 支持给参数命名。

```javascript
await acr.validate({
    nickname: 'foobar',
}, {
    nickname: acr.string('昵称').max(5),
});
```

这样，`nickname不能超过 5 个字符`就会变成 `昵称不能超过 5 个字符`。

可能你会觉得，这样写的话，在英文条件下，不就变成了 `昵称 must be at most 5 characters` 吗？也并不友好啊。我们考虑过这种情况，认为这个不应该是 acr 处理的范围，acr 只负责提供这么一个功能，不能负责翻译其中的内容。因此，你可以在你的应用中使用国际化的方法自行转换。比如在 egg 中：

```javascript
await acr.validate({
    nickname: 'foobar',
}, {
    nickname: acr.string(ctx.__('nickname')).max(5),
});
```

和数据转换一样，参数命名也支持配置的方式。参考 [配置](/acr/config.md)

## 错误模板

为了错误提示更加友好，基于 lodash 的 template，实现了一套简单的模板引擎。

```javascript
"{ name || path } required"
```

模板中，变量以大括号 `{}` 作为分割，大括号里面的区域可以是任何 js 代码。

我们内置了一些与此验证相关的变量，可以直接在模板中使用：

* `name` 参数名称，上文 参数命名 章节所设置的名称
* `path` 参数路径，实际上是参数在数据中的 key，命名为 path 是为后续打算实现的嵌套深度验证功能做准备
* `params` 此次验证传递的所有参数
