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
}
})
)
複製代碼
就先介紹到這,這個庫比較像是開發階段、測試使用的,可確保資料的結構、型態符合本身的要求,避免後續程序出錯,
並但願用直覺簡單的方式就能定義複雜的結構。
但願對你們能有所幫助,謝謝。