Skeletons 是一个简单直觉的纯JS资料验证庫javascript
当初专案须要将资料以JSON格式储存在本地端,万一资料结构出了问题或是不符合预其,后面程式都会出问题,所以想写一个简单直觉的纯JS资料验证方法,并开源到npm上。java
但愿对你们有帮助。喜欢能够给个星:) 有任何讨论都欢迎。git
先来介绍一下Javascript有趣的资料型态,若有错误请帮忙提出修正~github
JS 共有七种资料型态npm
其中包含六种 Primitive types :app
和 Object函数
特别的是 Function 广义来讲也是属于物件。测试
咱们能够用 typeof
来检查型态 (回传一个字串)ui
typeof 1 // 'number'
typeof "" // 'string'
typeof true // 'boolean'
typeof undefined // 'undefined'
typeof null // 'object'
typeof Symbol // 'symbol'
typeof function(){ } // 'function'
typeof {} // 'object'
复制代码
等等,你有没有发现什麽端倪?咱们一个一个看。this
通常咱们会直接定义变数:
let a = 1
复制代码
也能够用 function 定义
let a = Number(1)
typeof a // 'number'
复制代码
但若是加上 new
,则会建立一个Number物件
let a = new Number(1)
typeof a // 'object'
复制代码
NaN
也是属于Number
typeof NaN // 'number'
复制代码
若是要判断变数a
是可计算的数字且不是NaN
,如下是行不通的
if(typeof a==='number' && a!==NaN) //... a !== NaN 永远是 true
复制代码
由于 NaN
很特别,它不会等于任何值
// 如下统统都是 false !
NaN == 0
NaN == false
NaN == NaN
NaN === NaN
复制代码
你可能会想到用 boolean
来判断 true
/false
if(typeof a==='number' && !a) // ...
复制代码
可是别忘了还有个 0
:
if(typeof a==='number' && !a && a !== 0) // ...
复制代码
固然最简单的是用 isNaN
这个方法区分
if(typeof a==='number' && !isNaN(a)) // ...
复制代码
和 Number 很像,注意用new的话会同样是建立object。
let a = true // boolean
a = Boolean(true) //boolean
a = new Boolean(true) //object
复制代码
也是一种premitive type
undefined
和 null
是没有 funtion的 ,直接指定值就好
typeof undefined // 'undefined'
复制代码
值得一提的是,虽然如下都是否认值 (false)
Boolean(0)
Boolean(false)
Boolean('')
Boolean(undefined)
Boolean(null)
复制代码
但动态型别方面0, false, ''
是一伙的, undefined, null
则是另一个团体
0 == false // true
0 == '' // true
false == '' // true
undefined == null // true
undefined == false // false
undefined == 0 //false
null == '' //false
复制代码
null也是一种type,可是。。。
typeof null // 'object'
复制代码
没错,typeof
打印出来的是 'object'
上网查了一下,有些人说是JS当初设计的错误。
咱们要判断一个变数是物件的话能够这样:
if(typeof a === 'object' && a!==null) // ...
复制代码
最后一个 premitive type symbol
建立一个 symbol:
let a = Symbol()
typeof a // 'symbol'
复制代码
注意不能用 new
,会丢出错误
let a = new Symbol()
> Uncaught TypeError: Symbol is not a constructor
复制代码
除了上面六种 primitive type,其余都归类为物件
但特别的是 function,使用typeof
检查会回传function
字串:
typeof function(){} // 'function'
复制代码
让咱们能很好的区别 function 和其余通常的物件
接下来要介绍这个库了,有兴趣的话能够先看看介绍。
请先记好上面 Javascript 原生定义的资料型别,由于这个库的分类有些不同
Skeletons 中可定义的类型除了本来的七种JS类型,额外分出 array 和 function
缘由是这两个都是很经常使用的,将他们从物件特别区分出来。
定义一个规则,使用 validate
来验证资料
const rule = new Skeletons(schema)
rule.validate(data)
复制代码
定义规则须要传入一个schema
,也就是你设想的资料结构以及形态
schema 能够有四种
1. premitive type function
共有四种能够用 (undefined和null是没有function的,咱们后面谈如何定义)
分别定义四种形态,使用上不用呼叫,直接传入function
以下,定义一个型态为数字的schema
const schema = Number
复制代码
2. 使用 object literal
使用最值觉的 object literal 来定义一个物件 (注意,在Skeletons会排除array和function)的key
每一个key均可指派另外一个schema
以下定义了一个有 x, y 两个键的物件,且两个键的值都是数字型态
const schema = {
x: Number,
y: Number
}
复制代码
使用这种方式,让你可以轻易地定义结构较深的物件
const userSchema = {
name: String,
id: String,
VIP: {
code: Number,
details: {
type: String,
level: Number,
expired: Boolean
}
},
}
复制代码
3. array literal
使用array literal来定义有固定元素數量的array
const schema = [String, Number, Skeletons.Function()]
复制代码
4.呼叫Skeletons的静态方法
共有十种方法,分别表明是五种premitive type (不含undefined)、Object, 从物件中分出来的 Array, Function,以及特殊的Any(任何非undefined的型态) 和 MapObject
每种方法都接受一个options
物件当作参数,
且均可定义三个基本的property
options.required
type: Boolean
default: true
Skeletons对于任何 undefined
值都会认定为验证失败:
new Skeletons({
a: Number
}).validate({})
// data.a got undefined, validation filed
复制代码
若是要容许该层资料能够为 undefined
,设 options.required
为 false
new Skeletons({
a: Skeletons.Number({
required: false
})
})
复制代码
options.default
type: 任何
default: undefined
有时后资料的预设值(或者空值)的型态可能会和资料有值的时后不同,比方说有人可能会用null
来替代空的物件。
new Skeletons(Skeletons.Object({
default: null
}))
复制代码
options.validator
type: Function
传入一个function,回传true
/false
来验证资料
validator(value, data)
复制代码
该函数可接收两个参数:value
表明该层资料的值,data
表明整个资料
如下这个例子,value
等于120
, data
等于整个datasource
const datasource = {
a: 120,
b: 240
}
new Skeletons({
a: Skeletons.Number({
validator: (val, data) => {
// in this case, val = 120, data = datasource
return val === data.b*2
}
}),
b: Number
})
复制代码
更多详细的介绍能够参考文件
验证可分为
如何设定可参考文件
每次验证后,可由warnings
属性得到错误资讯
const rule = new Skeletons(Number)
rule.validate('1')
rule.warnings // 一串array 包含全部错误资讯
复制代码
关于错误资讯可参考warnings
接下来演示一些资料定义的范例
定义一个schema
表明不是NaN
的number
// ex: 1
const calcNum = Skeletons.Number({
allowNaN: false
})
复制代码
定义一个array
,每一个元素是含有x
,y
属性,值为非NaN
数字的物件
// ex: [{x: 1, y: 2}, {x: 3, y: 5}]
new Skeletons(
Skeletons.Array({
item: {
x: calcNum,
y: calcNum
}
})
)
复制代码
规定array
必定要有元素
// ex: [{x: 1, y: 2}, {x: 3, y: 5}]
new Skeletons(
Skeletons.Array({
validator: ary=>ary.length>0,
item: {
x: calcNum,
y: calcNum
}
})
)
复制代码
假设有一笔资料,当age
大于 18,grownup
等于true
表明已成年,反之则为false
const ex = {
age: 19,
grownup: true
}
复制代码
咱们能够用 validator
来进行检查
new Skeletons(
{
age: Number,
grownup: Skeletons.Boolean({
validator: (val, data) => val === data.age>=18
})
}
).validate(ex)
复制代码
有时后物件做为一个相似map来除存对应的key,表明并无固定的属性值和数量。这时可使用 MapObject
例如 room
以房间的id当作key来mapping
const room = {
idkfd: {
name : 'have fun',
members: 4,
id: 'idkfd'
},
ckclo: {
name : 'My room',
members: 2,
id: 'ckclo'
},
ppqkd: {
name : 'User0001\'s room',
members: 8,
id: 'ppqkd'
}
}
复制代码
可这样定义
new Skeletons(
Skeletons.MapObject({
keyValidator: (k, data)=> k === data[k].id,
item: {
name: String,
members: Number,
id: String
}
})
)
复制代码
就先介绍到这,这个库比较像是开发阶段、测试使用的,可确保资料的结构、型态符合本身的要求,避免后续程序出错,
并但愿用直觉简单的方式就能定义复杂的结构。
但愿对你们能有所帮助,谢谢。