Skip to content
This repository has been archived by the owner on Dec 25, 2017. It is now read-only.

Commit

Permalink
perf(validation): improve validation performance
Browse files Browse the repository at this point in the history
  • Loading branch information
kazupon committed Mar 10, 2016
1 parent 420deb6 commit 3e79962
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 131 deletions.
6 changes: 3 additions & 3 deletions src/directives/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ export default function (Vue) {
paramWatchers: {
detectBlur (val, old) {
this.validation.detectBlur = this.isDetectBlur(val)
this.validator.validate()
this.validator.validate(this.field)
},

detectChange (val, old) {
this.validation.detectChange = this.isDetectChange(val)
this.validator.validate()
this.validator.validate(this.field)
}
},

Expand Down Expand Up @@ -61,7 +61,7 @@ export default function (Vue) {
this.handleArray(value)
}

this.validator.validate()
this.validator.validate(this.field)
},

unbind () {
Expand Down
2 changes: 0 additions & 2 deletions src/directives/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ export default function (Vue) {
_.extend(vm.$options, { _validator: this.validatorName })
this.factory = new FragmentFactory(vm, this.el.innerHTML)
vIf.insert.call(this)

this.validator.validate()
})

!lazy && vm.$activateValidator()
Expand Down
2 changes: 1 addition & 1 deletion src/validations/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export default class BaseValidation {
this.willUpdateDirty(el)
this.willUpdateModified(el)

this._validator.validate()
this._validator.validate(this.field)
}

validate (cb) {
Expand Down
4 changes: 2 additions & 2 deletions src/validations/checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export default class CheckboxValidation extends BaseValidation {
})
}
} else {
this._validator.validate()
this._validator.validate(this.field)
}
}

Expand All @@ -64,7 +64,7 @@ export default class CheckboxValidation extends BaseValidation {
if (found === -1) { return }

this._inits.splice(found, 1)
this._validator.validate()
this._validator.validate(this.field)
}

willUpdateFlags () {
Expand Down
4 changes: 2 additions & 2 deletions src/validations/radio.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default class RadioValidation extends BaseValidation {
}
})
} else {
this._validator.validate()
this._validator.validate(this.field)
}
}

Expand All @@ -44,7 +44,7 @@ export default class RadioValidation extends BaseValidation {
if (found === -1) { return }

this._inits.splice(found, 1)
this._validator.validate()
this._validator.validate(this.field)
}

willUpdateFlags () {
Expand Down
123 changes: 60 additions & 63 deletions src/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,21 +46,7 @@ export default class Validator {

// define the validate manually meta method to vue instance
vm.$validate = (...args) => {
let field = null
let touched = false
let cb = null

each(args, (arg, index) => {
if (typeof arg === 'string') {
field = arg
} else if (typeof arg === 'boolean') {
touched = arg
} else if (typeof arg === 'function') {
cb = arg
}
})

this._validate(field, touched, cb)
this.validate(...args)
}

// define manually the validation errors
Expand Down Expand Up @@ -169,34 +155,33 @@ export default class Validator {
validations && pull(validations, validation)
}

validate (cb) {
const scope = this._scope

this._runValidates((validation, key, done) => {
validation.validate((results) => {
util.Vue.set(scope, key, results)
done()
})
}, () => { // finished
scope.touched && this._fireEvent('touched')
scope.dirty && this._fireEvent('dirty')
validate (...args) {
let field = null
let touched = false
let cb = null

if (this._modified !== scope.modified) {
this._fireEvent('modified', scope.modified)
this._modified = scope.modified
each(args, (arg, index) => {
if (typeof arg === 'string') {
field = arg
} else if (typeof arg === 'boolean') {
touched = arg
} else if (typeof arg === 'function') {
cb = arg
}

let valid = scope.valid
this._fireEvent((valid ? 'valid' : 'invalid'))

cb && cb()
})

if (!field) { // all
each(this.validations, (validation, key) => {
validation.willUpdateFlags(touched)
})
this._validates(cb)
} else { // each field
this._validate(field, touched, cb)
}
}

setupScope () {
let validationsGetter = () => { return this.validations }
let scopeGetter = () => { return this._scope }
this._defineProperties(validationsGetter, scopeGetter)
this._defineProperties(() => { return this.validations }, () => { return this._scope })

each(this._groups, (name) => {
let validations = this._groupValidations[name]
Expand All @@ -216,38 +201,35 @@ export default class Validator {
}
}


_validate (field, touched, cb) {
_validate (field, touched = false, cb = null) {
const scope = this._scope

if (!field) { // all
each(this.validations, (validation, key) => {
validation.willUpdateFlags(touched)
let validation = this._getValidationFrom(field)
if (validation) {
validation.willUpdateFlags(touched)
validation.validate((results) => {
util.Vue.set(scope, field, results)
this._fireEvents()
cb && cb()
})
this.validate(cb)
} else { // each field
let validation = this._getValidationFrom(field)
if (validation) {
validation.willUpdateFlags(touched)
validation.validate((results) => {
util.Vue.set(scope, field, results)

scope.dirty && this._fireEvent('dirty')

if (this._modified !== scope.modified) {
this._fireEvent('modified', scope.modified)
this._modified = scope.modified
}
}
}

let valid = scope.valid
this._fireEvent((valid ? 'valid' : 'invalid'))
_validates (cb) {
const scope = this._scope

cb && cb()
})
}
}
this._runValidates((validation, key, done) => {
validation.validate((results) => {
util.Vue.set(scope, key, results)
done()
})
}, () => { // finished
this._fireEvents()
cb && cb()
})
}


_getValidationFrom (field) {
let validation = this._validations[field]
if (!validation && this._checkboxValidations[field]) {
Expand All @@ -262,7 +244,7 @@ export default class Validator {
each(this.validations, (validation, key) => {
validation.reset()
})
this.validate(cb)
this._validates(cb)
}

_setValidationErrors (errors) {
Expand Down Expand Up @@ -388,6 +370,21 @@ export default class Validator {
handler && handler.apply(null, args)
}

_fireEvents () {
const scope = this._scope

scope.touched && this._fireEvent('touched')
scope.dirty && this._fireEvent('dirty')

if (this._modified !== scope.modified) {
this._fireEvent('modified', scope.modified)
this._modified = scope.modified
}

let valid = scope.valid
this._fireEvent(valid ? 'valid' : 'invalid')
}

_getEventName (type) {
return this.name + ':' + type
}
Expand Down
1 change: 1 addition & 0 deletions test/specs/event.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ describe('event', () => {
input1.value = 'foo'
input2.value = 'bar'
trigger(input1, 'input')
trigger(input2, 'input')
})
})
})
Expand Down
118 changes: 60 additions & 58 deletions test/specs/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,28 @@ describe('$validate', () => {
field1.value = '11'
field2.value = 'hi'
vm.$nextTick(() => {
vm.$validate('field1')
vm.$validate('field2')

assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.min === false)
assert(vm.$validator1.field1.max === true)
assert(vm.$validator1.field1.valid === false)
assert(vm.$validator1.field1.dirty === true)
assert(vm.$validator1.field1.modified === true)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field2.minlength === true)
assert(vm.$validator1.field2.valid === false)
assert(vm.$validator1.field2.dirty === true)
assert(vm.$validator1.field2.modified === true)
assert(vm.$validator1.field2.touched === false)
assert(vm.$validator1.valid === false)
assert(vm.$validator1.dirty === true)
assert(vm.$validator1.modified === true)
assert(vm.$validator1.touched === false)

done()
vm.$validate('field1', () => {
vm.$validate('field2', () => {
assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.min === false)
assert(vm.$validator1.field1.max === true)
assert(vm.$validator1.field1.valid === false)
assert(vm.$validator1.field1.dirty === true)
assert(vm.$validator1.field1.modified === true)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field2.minlength === true)
assert(vm.$validator1.field2.valid === false)
assert(vm.$validator1.field2.dirty === true)
assert(vm.$validator1.field2.modified === true)
assert(vm.$validator1.field2.touched === false)
assert(vm.$validator1.valid === false)
assert(vm.$validator1.dirty === true)
assert(vm.$validator1.modified === true)
assert(vm.$validator1.touched === false)

done()
})
})
})
})
})
Expand Down Expand Up @@ -166,23 +167,24 @@ describe('$validate', () => {
radio3.checked = true
vm.$nextTick(() => {
vm.$validate('field1', () => {
vm.$validate('field2')
assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.valid === true)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field1.dirty === true)
assert(vm.$validator1.field1.modified === true)
assert(vm.$validator1.field2.required === false)
assert(vm.$validator1.field2.valid === true)
assert(vm.$validator1.field2.touched === false)
assert(vm.$validator1.field2.dirty === true)
assert(vm.$validator1.field2.modified === true)
assert(vm.$validator1.valid === true)
assert(vm.$validator1.touched === false)
assert(vm.$validator1.dirty === true)
assert(vm.$validator1.modified === true)

done()
vm.$validate('field2', () => {
assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.valid === true)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field1.dirty === true)
assert(vm.$validator1.field1.modified === true)
assert(vm.$validator1.field2.required === false)
assert(vm.$validator1.field2.valid === true)
assert(vm.$validator1.field2.touched === false)
assert(vm.$validator1.field2.dirty === true)
assert(vm.$validator1.field2.modified === true)
assert(vm.$validator1.valid === true)
assert(vm.$validator1.touched === false)
assert(vm.$validator1.dirty === true)
assert(vm.$validator1.modified === true)

done()
})
})
})
})
Expand Down Expand Up @@ -282,26 +284,26 @@ describe('$validate', () => {
field1.value = '11'
field2.value = 'hi'
vm.$nextTick(() => {
vm.$validate()

assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.min === false)
assert(vm.$validator1.field1.max === true)
assert(vm.$validator1.field1.valid === false)
assert(vm.$validator1.field1.dirty === true)
assert(vm.$validator1.field1.modified === true)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field2.minlength === true)
assert(vm.$validator1.field2.valid === false)
assert(vm.$validator1.field2.dirty === true)
assert(vm.$validator1.field2.modified === true)
assert(vm.$validator1.field2.touched === false)
assert(vm.$validator1.valid === false)
assert(vm.$validator1.dirty === true)
assert(vm.$validator1.modified === true)
assert(vm.$validator1.touched === false)

done()
vm.$validate(() => {
assert(vm.$validator1.field1.required === false)
assert(vm.$validator1.field1.min === false)
assert(vm.$validator1.field1.max === true)
assert(vm.$validator1.field1.valid === false)
assert(vm.$validator1.field1.dirty === true)
assert(vm.$validator1.field1.modified === true)
assert(vm.$validator1.field1.touched === false)
assert(vm.$validator1.field2.minlength === true)
assert(vm.$validator1.field2.valid === false)
assert(vm.$validator1.field2.dirty === true)
assert(vm.$validator1.field2.modified === true)
assert(vm.$validator1.field2.touched === false)
assert(vm.$validator1.valid === false)
assert(vm.$validator1.dirty === true)
assert(vm.$validator1.modified === true)
assert(vm.$validator1.touched === false)

done()
})
})
})
})
Expand Down

0 comments on commit 3e79962

Please sign in to comment.