辅助函数和方法
AdonisJS 将框架或生态系统包使用的实用程序捆绑到一个 辅助函数 模块中,并将它们运用到你的应用程序代码中。
由于框架已经安装并使用了这些实用程序,因此 辅助函数 模块不会向你的 node_modules
添加任何额外的会让空间膨胀的内容。
字符串辅助函数
字符串助手函数公开了以下转换方法。
camelCase
将字符串转换为其 camelCase
版本。
import { string } from '@ioc:Adonis/Core/Helpers'
string.camelCase('hello-world') // helloWorld
snakeCase
将字符串转换为其 snake_case
版本。
import { string } from '@ioc:Adonis/Core/Helpers'
string.snakeCase('helloWorld') // hello_world
dashCase
将字符串转换为其 dash-case
版本。或者,你还可以将每个段的第一个字母大写。
import { string } from '@ioc:Adonis/Core/Helpers'
string.dashCase('helloWorld') // hello-world
string.dashCase('helloWorld', { capitalize: true }) // Hello-World
pascalCase
将字符串转换为其 PascalCase
版本。
import { string } from '@ioc:Adonis/Core/Helpers'
string.pascalCase('helloWorld') // HelloWorld
capitalCase
将字符串大写
import { string } from '@ioc:Adonis/Core/Helpers'
string.capitalCase('helloWorld') // Hello World
sentenceCase
将字符串转换为句子
import { string } from '@ioc:Adonis/Core/Helpers'
string.sentenceCase('hello-world') // Hello world
dotCase
将字符串转换为其 dot.case
版本。
import { string } from '@ioc:Adonis/Core/Helpers'
string.dotCase('hello-world') // hello.world
noCase
移除所有类型的 Case
import { string } from '@ioc:Adonis/Core/Helpers'
string.noCase('hello-world') // hello world
string.noCase('hello_world') // hello world
string.noCase('helloWorld') // hello world
titleCase
将句子转换为标题大小写
import { string } from '@ioc:Adonis/Core/Helpers'
string.titleCase('Here is a fox') // Here Is a Fox
pluralize
将词汇转为复数形式。
import { string } from '@ioc:Adonis/Core/Helpers'
string.pluralize('box') // boxes
string.pluralize('i') // we
你还可以使用 defineIrregularRule
方法定义自己的复数规则。该方法接受单数形式作为第一个参数,复数形式作为第二个参数。
import { string } from '@ioc:Adonis/Core/Helpers'
string.defineIrregularRule('auth', 'auth')
string.plural('auth') // auth
你还可以使用 defineUncountableRule
方法定义自己的不可数规则。
import { string } from '@ioc:Adonis/Core/Helpers'
string.defineUncountableRule('login')
string.plural('login') // home
truncate
在给定数量的字符后截断字符串
import { string } from '@ioc:Adonis/Core/Helpers'
string.truncate(
'This is a very long, maybe not that long title',
12
) // This is a ve...
默认情况下,字符串在给定字符之后被截断。但是,你可以指示该方法等待单词完成。
string.truncate(
'This is a very long, maybe not that long title',
12,
{
completeWords: true
}
) // This is a very...
此外,还可以自定义后缀。
string.truncate(
'This is a very long, maybe not that long title',
12,
{
completeWords: true,
suffix: ' <a href="/1"> Read more </a>',
}
) // This is a very <a href="/1"> Read more </a>
excerpt
excerpt
方法与 truncate
方法相同。但是,它会从字符串中去除 HTML。
import { string } from '@ioc:Adonis/Core/Helpers'
string.excerpt(
'<p>This is a <strong>very long</strong>, maybe not that long title</p>',
12
) // This is a very...
condenseWhitespace
压缩给定字符串中的空格。该方法从left
、right
和单词之间的多个空格中删除空格。
import { string } from '@ioc:Adonis/Core/Helpers'
string.condenseWhitespace(' hello world ')
// hello world
escapeHTML
从字符串中转义 HTML
import { string } from '@ioc:Adonis/Core/Helpers'
string.escapeHTML('<p> foo © bar </p>')
// <p> foo © bar </p>
此外,您还可以对非 ASCII 符号进行编码。
import { string } from '@ioc:Adonis/Core/Helpers'
string.escapeHTML(
'<p> foo © bar </p>',
{
encodeSymbols: true
}
)
// <p> foo © bar </p>
encodeSymbols
编码符号. 查看 he 以获取可用选项
import { string } from '@ioc:Adonis/Core/Helpers'
string.encodeSymbols('foo © bar')
// foo © bar
toSentence
用分隔符连接单词数组。
import { string } from '@ioc:Adonis/Core/Helpers'
string.toSentence([
'route',
'middleware',
'controller'
]) // 路由、中间件和控制器
string.toSentence([
'route',
'middleware'
]) // 路由和中间件
您可以定义以下选项来自定义输出。
-separator
是两个单词之间的值,除了最后一个。
-pairSeparator
是第一个词和最后一个词之间的值。使用,仅当有两个单词时
-lastSeparator
是倒数第二个和最后一个单词之间的值。仅在有两个以上单词时使用。
string.toSentence([
'route',
'middleware',
'controller'
], {
separator: '/ ',
lastSeparator: '/or '
}) // 路由/中间件/或控制器
prettyBytes
将字节值转换为人类可读的字符串。有关选项,请参考 bytes 包.
import { string } from '@ioc:Adonis/Core/Helpers'
string.prettyBytes(1024) // 1KB
string.prettyBytes(1024, { unitSeparator: ' ' }) // 1 KB
toBytes
将人类可读的字符串转换为字节。此方法与 prettyBytes
方法相反。
import { string } from '@ioc:Adonis/Core/Helpers'
string.toBytes('1KB') // 1024
prettyMs
Convert time in milliseconds to a human-readable string
import { string } from '@ioc:Adonis/Core/Helpers'
string.prettyMs(60000) // 1 分钟
string.prettyMs(60000, { long: true }) // 1 分钟
toMs
将人类可读的字符串转换为毫秒。此方法与prettyMs
方法相反。
import { string } from '@ioc:Adonis/Core/Helpers'
string.toMs('1min') // 60000
ordinalize
对字符串或数值进行排序
import { string } from '@ioc:Adonis/Core/Helpers'
string.ordinalize(1) // 第一个
string.ordinalize(99) // 第 99 个
generateRandom
生成加密强的随机字符串
import { string } from '@ioc:Adonis/Core/Helpers'
string.generateRandom(32)
isEmpty
查找值是否为空。还检查带有所有空格的空字符串
import { string } from '@ioc:Adonis/Core/Helpers'
string.isEmpty('') // true
string.isEmpty(' ') // true
Type detection
JavaScript 中的类型检测非常薄弱,经常会导致意想不到的错误。例如:typeof null
是 object 并且 typeof []
也是一个 object。
您可以使用 types
帮助器在您的应用程序中进行更准确和一致的类型检查。
lookup
lookup
方法返回给定值的类型。
import { types } from '@ioc:Adonis/Core/Helpers'
types.lookup({}) // 对象
types.lookup([]) // 数组
types.lookup(Object.create(null)) // 对象
types.lookup(null) // 空
types.lookup(function () {}) // 函数
types.lookup(class Foo {}) // 类
types.lookup(new Map()) // map
isNull
判断给定值是否为空对象(Null)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isNull(null) // true
isBoolean
判断给定值是否为布尔类型(Boolean)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isBoolean(true) // true
isBuffer
判断给定值是否为缓冲区对象(Buffer)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isBuffer(new Buffer()) // true
isNumber
判断给定值是否为数字(Number)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isNumber(100) // true
isString
判断给定值是否为字符串(String)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isString('hello') // true
isArguments
判断传入的参数值是否为对象(Object)
import { types } from '@ioc:Adonis/Core/Helpers'
function foo() {
types.isArguments(arguments) // true
}
isObject
判断给定的值是否为简单对象
import { types } from '@ioc:Adonis/Core/Helpers'
types.isObject({}) // true
isDate
判断给定的值是否为简单日期对象(Date)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isDate(new Date()) // true
isArray
判断给定的值是否为数组(Array)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isArray([1, 2, 3]) // true
isRegexp
判断给定的值是否为正则表达式对象(RegExp)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isRegexp(/[a-z]+/) // true
isError
判断给定的值是否为错误对象(Error)或异常对象(Exception)
import { types } from '@ioc:Adonis/Core/Helpers'
import { Exception } from '@poppinss/utils'
types.isError(new Error('foo')) // true
types.isError(new Exception('foo')) // true
isFunction
判断给定的值是否为函数(Function)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isFunction(function foo() {}) // true
isClass
判断给定的值是否为类(Class),具体实现是通过正则表达式区分类(Class)与函数(Function)
import { types } from '@ioc:Adonis/Core/Helpers'
class User {}
types.isClass(User) // true
types.isFunction(User) // false
isInteger
判断给定的值是否为整型(Integer)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isInteger(22.00) // true
types.isInteger(22) // true
types.isInteger(-1) // true
types.isInteger(-1.00) // true
types.isInteger(22.10) // false
types.isInteger(.3) // false
types.isInteger(-.3) // false
isFloat
判断给定的值是否为浮点型(Float)
import { types } from '@ioc:Adonis/Core/Helpers'
types.isFloat(22.10) // true
types.isFloat(-22.10) // true
types.isFloat(.3) // true
types.isFloat(-.3) // true
types.isFloat(22.00) // false
types.isFloat(-22.00) // false
types.isFloat(-22) // false
isDecimal
判断给定的值是否为十进制数字,给定的值可以是数字也可以是数字字符串,数值类型通过调用 toString()
方法转换为字符串
之所以需要转换为字符串是通过正则表达式来判断其是否为合法十进制数字,因为JavaScript原生无法判断十进制值
import { types } from '@ioc:Adonis/Core/Helpers'
types.isDecimal('22.10') // true
types.isDecimal(22.1) // true
types.isDecimal('-22.10') // true
types.isDecimal(-22.1) // true
types.isDecimal('.3') // true
types.isDecimal(0.3) // true
types.isDecimal('-.3') // true
types.isDecimal(-0.3) // true
types.isDecimal('22.00') // true
types.isDecimal(22.0) // false (转换为22)
types.isDecimal('-22.00') // true
types.isDecimal(-22.0) // false (转换为-22)
types.isDecimal('22') // false
types.isDecimal(22) // false
types.isDecimal('0.0000000000001') // true
types.isDecimal(0.0000000000001) // false (转换为1e-13)
safeEqual
通过避免 时序攻击。将两个值相互比较。此方法内部使用 crypto.timingSafeEqual 方法,但也可以比较两个字符串。
import { safeEqual } from '@ioc:Adonis/Core/Helpers'
if (safeEqual('hello world', 'hello world')) {
}
requireAll
Helper 需要目录中的所有.js
、.ts
和.json
文件。此方法仅适用于 commonjs 模块,不适用于 ES 模块。
import { join } from 'path'
import { requireAll } from '@ioc:Adonis/Core/Helpers'
const configTree = requireAll(join(__dirname, 'config'))
默认情况下,文件是递归导入的。但是,您可以通过将第二个参数设置为 false
来关闭递归扫描
requireAll(join(__dirname, 'config'), false)
缺少根目录时会引发异常。但是,您可以通过将第三个参数设置为 true
来指示该方法忽略丢失的目录。
requireAll(join(__dirname, 'config'), true, true)
fsReadAll
递归扫描所有并收集给定目录中所有.js
、.ts
和.json
文件的路径。
import { join } from 'path'
import { fsReadAll } from '@ioc:Adonis/Core/Helpers'
fsReadAll(join(__dirname, 'config'))
// ['app.ts', 'bodyparser.ts', 'cors.ts']
或者,您可以定义自定义过滤器函数来忽略某些路径。定义自定义过滤器将删除仅选择.js
、.ts
和.json
文件的现有过滤器。
fsReadAll(join(__dirname, 'config'), (filePath) => {
return filePath.endsWith('.md')
})
base64
编码/解码 Base64 值。如果要将编码值传递给 URL,请使用urlEncode
和urlDecode
方法。
import { base64 } from '@ioc:Adonis/Core/Helpers'
base64.encode('hello world')
base64.decode(base64.encode('hello world'))
// URL 安全编码
base64.urlEncode('hello world')
base64.urlDecode(base64.urlEncode('hello world'))
你也可以为输入值定义自定义编码。
const encoded = base64.encode(bufferValue, 'binary')
base64.decode(encoded, 'binary')
interpolate
一种轻量级的辅助方法,用于在字符串中插入花括号。此方法不能替代任何模板引擎。
import { interpolate } from '@ioc:Adonis/Core/Helpers'
interpolate('hello {{ username }}', { username: 'virk' })
// 嵌套值
interpolate('hello {{ user.username }}', {
user: { username: 'virk' }
})
// 对象数组
interpolate('hello {{ users.0.username }}', {
users: [{ username: 'virk' }]
})
// 字面值数组
interpolate('hello {{ scores.0 }}', {
scores: [67, 80]
})
compose
JavaScript 没有同时继承多个类的概念,TypeScript 也没有。但是,TypeScript 的 官方文档 确实谈到了 mixins (混合)的概念。
根据 TypeScript 文档,可以按如下方式创建和应用 mixin。
type Constructor = new (...args: any[]) => any
const UserWithEmail = <T extends Constructor>(superclass: T) => {
return class extends superclass {
public email: string
}
}
const UserWithPassword = <T extends Constructor>(superclass: T) => {
return class extends superclass {
public password: string
}
}
class BaseModel {}
class User extends UserWithPassword(UserWithEmail(BaseModel)) {}
Mixin 接近于继承多个类的完美方式,建议阅读 这篇文章。
但是,应用多个 mixins 的语法很繁琐,因为你必须在 mixins 上应用 mixins,创建了一个嵌套层次结构,如下所示:
class User extends UserWithAttributes(
UserWithAge(
UserWithPassword(
UserWithEmail(BaseModel)
)
)
) {}
compose
方法是一个小工具,可以稍微改进语法。
import { compose } from '@ioc:Adonis/Core/Helpers'
class User extends compose(
BaseModel,
UserWithPassword,
UserWithEmail,
UserWithAge,
UserWithAttributes
) {}
Mixins gotchas
TypeScript 有一个与 mixin 类或基类的构造函数参数相关的 open issue。
TypeScript 期望 mixin 链中使用的所有类都有一个构造函数,其参数只有一个...args: any[]
。例如:以下代码在运行时可以正常工作,但 TypeScript 编译器会报错。
class BaseModel {
constructor(name: string) {}
}
const UserWithEmail = <T extends typeof BaseModel>(superclass: T) => {
return class extends superclass {
// ERROR: A mixin class must have a constructor with a single rest parameter of type 'any[]'.ts(2545)
public email: string
}
}
class User extends compose(BaseModel, UserWithEmail) {}
您可以通过使用NormalizeConstructor
类型覆盖基类的构造函数来解决此问题。
import {
compose,
NormalizeConstructor
} from '@ioc:Adonis/Core/Helpers'
const UserWithEmail = <T extends NormalizeConstructor<typeof BaseModel>>(
superclass: T
) => {
return class extends superclass {
public email: string
}
}
cuid
生成一个 防碰撞 ID.
import { cuid } from '@ioc:Adonis/Core/Helpers'
cuid()
// cjld2cjxh0000qzrmn831i7rn
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。