1
0
mirror of synced 2024-11-22 05:16:05 +03:00

refactor: Typehinting improvals, moved registry class, improved logic of shallow equal checker

This commit is contained in:
Zaytsev Kirill 2021-05-22 20:35:57 +03:00
parent e6271bb069
commit 7aca27a010
7 changed files with 63 additions and 53 deletions

View File

@ -16,7 +16,7 @@ import {
Prop, Prop,
Watch, Watch,
} from 'vue-property-decorator' } from 'vue-property-decorator'
import { arrayify, has, shallowEqualObjects, snakeToCamel } from './utils' import { arrayify, has, shallowEquals, snakeToCamel } from './utils'
import { import {
processConstraints, processConstraints,
validate, validate,
@ -102,7 +102,7 @@ export default class FormularioField extends Vue {
private set model (value: unknown) { private set model (value: unknown) {
value = this.modelSetConverter(value, this.proxy) value = this.modelSetConverter(value, this.proxy)
if (!shallowEqualObjects(value, this.proxy)) { if (!shallowEquals(value, this.proxy)) {
this.proxy = value this.proxy = value
} }
@ -153,7 +153,7 @@ export default class FormularioField extends Vue {
@Watch('proxy') @Watch('proxy')
private onProxyChange (newValue: unknown, oldValue: unknown): void { private onProxyChange (newValue: unknown, oldValue: unknown): void {
if (!this.hasModel && !shallowEqualObjects(newValue, oldValue)) { if (!this.hasModel && !shallowEquals(newValue, oldValue)) {
this.context.model = newValue this.context.model = newValue
} }
if (this.validationBehavior === VALIDATION_BEHAVIOR.LIVE) { if (this.validationBehavior === VALIDATION_BEHAVIOR.LIVE) {
@ -165,7 +165,7 @@ export default class FormularioField extends Vue {
@Watch('value') @Watch('value')
private onValueChange (newValue: unknown, oldValue: unknown): void { private onValueChange (newValue: unknown, oldValue: unknown): void {
if (this.hasModel && !shallowEqualObjects(newValue, oldValue)) { if (this.hasModel && !shallowEquals(newValue, oldValue)) {
this.context.model = newValue this.context.model = newValue
} }
} }
@ -199,14 +199,14 @@ export default class FormularioField extends Vue {
private initProxy (): void { private initProxy (): void {
// This should only be run immediately on created and ensures that the // This should only be run immediately on created and ensures that the
// proxy and the model are both the same before any additional registration. // proxy and the model are both the same before any additional registration.
if (!shallowEqualObjects(this.context.model, this.proxy)) { if (!shallowEquals(this.context.model, this.proxy)) {
this.context.model = this.proxy this.context.model = this.proxy
} }
} }
runValidation (): Promise<void> { runValidation (): Promise<Violation[]> {
this.validationRun = this.validate().then(violations => { this.validationRun = this.validate().then(violations => {
const validationChanged = !shallowEqualObjects(violations, this.violations) const validationChanged = !shallowEquals(violations, this.violations)
this.violations = violations this.violations = violations
if (validationChanged) { if (validationChanged) {
const payload = { const payload = {
@ -221,6 +221,7 @@ export default class FormularioField extends Vue {
return this.violations return this.violations
}) })
return this.validationRun return this.validationRun
} }

View File

@ -19,10 +19,10 @@ import {
has, has,
merge, merge,
setNested, setNested,
shallowEqualObjects, shallowEquals,
} from '@/utils' } from '@/utils'
import Registry from '@/form/registry' import FormularioFormRegistry from '@/FormularioFormRegistry'
import FormularioField from '@/FormularioField.vue' import FormularioField from '@/FormularioField.vue'
@ -54,7 +54,7 @@ export default class FormularioForm extends Vue {
public proxy: Record<string, unknown> = {} public proxy: Record<string, unknown> = {}
private registry: Registry = new Registry(this) private registry: FormularioFormRegistry = new FormularioFormRegistry(this)
private errorObserverRegistry = new ErrorObserverRegistry() private errorObserverRegistry = new ErrorObserverRegistry()
// Local error messages are temporal, they wiped each resetValidation call // Local error messages are temporal, they wiped each resetValidation call
@ -174,12 +174,12 @@ export default class FormularioForm extends Vue {
const oldValue = getNested(this.proxy, fqn) const oldValue = getNested(this.proxy, fqn)
const newValue = getNested(values, fqn) const newValue = getNested(values, fqn)
if (!shallowEqualObjects(newValue, oldValue)) { if (!shallowEquals(newValue, oldValue)) {
this.setFieldValue(fqn, newValue) this.setFieldValue(fqn, newValue)
proxyHasChanges = true proxyHasChanges = true
} }
if (!shallowEqualObjects(newValue, $field.proxy)) { if (!shallowEquals(newValue, $field.proxy)) {
$field.context.model = newValue $field.context.model = newValue
} }
}) })

View File

@ -1,4 +1,5 @@
import { shallowEqualObjects, has, getNested } from '@/utils' import { getNested, has, shallowEquals } from '@/utils'
import FormularioField from '@/FormularioField.vue' import FormularioField from '@/FormularioField.vue'
import FormularioForm from '@/FormularioForm.vue' import FormularioForm from '@/FormularioForm.vue'
@ -6,7 +7,7 @@ import FormularioForm from '@/FormularioForm.vue'
* Component registry with inherent depth to handle complex nesting. This is * Component registry with inherent depth to handle complex nesting. This is
* important for features such as grouped fields. * important for features such as grouped fields.
*/ */
export default class Registry { export default class FormularioFormRegistry {
private ctx: FormularioForm private ctx: FormularioForm
private registry: Map<string, FormularioField> private registry: Map<string, FormularioField>
@ -42,7 +43,7 @@ export default class Registry {
// @ts-ignore // @ts-ignore
component.context.model = value component.context.model = value
// @ts-ignore // @ts-ignore
} else if (hasModel && !shallowEqualObjects(component.proxy, value)) { } else if (hasModel && !shallowEquals(component.proxy, value)) {
// In this case, the field is v-modeled or has an initial value and the // In this case, the field is v-modeled or has an initial value and the
// form has no value or a different value, so use the field value // form has no value or a different value, so use the field value
// @ts-ignore // @ts-ignore

View File

@ -4,7 +4,7 @@ export { default as has } from './has'
export { isScalar } from './types' export { isScalar } from './types'
export { default as merge } from './merge' export { default as merge } from './merge'
export { default as regexForFormat } from './regexForFormat' export { default as regexForFormat } from './regexForFormat'
export { default as shallowEqualObjects } from './shallowEqualObjects' export { default as shallowEquals } from './shallowEquals'
export { default as snakeToCamel } from './snakeToCamel' export { default as snakeToCamel } from './snakeToCamel'
export function getNested (obj: Record<string, any>, field: string): any { export function getNested (obj: Record<string, any>, field: string): any {

View File

@ -1,34 +0,0 @@
export default function shallowEqualObjects (objA: Record<string, any>, objB: Record<string, any>): boolean {
if (objA === objB) {
return true
}
if (!objA || !objB) {
return false
}
const aKeys = Object.keys(objA)
const bKeys = Object.keys(objB)
if (bKeys.length !== aKeys.length) {
return false
}
if (objA instanceof Date && objB instanceof Date) {
return objA.getTime() === objB.getTime()
}
if (aKeys.length === 0) {
return objA === objB
}
for (let i = 0; i < aKeys.length; i++) {
const key = aKeys[i]
if (objA[key] !== objB[key]) {
return false
}
}
return true
}

View File

@ -0,0 +1,42 @@
export function equalsDates (a: Date, b: Date): boolean {
return a.getTime() === b.getTime()
}
export function shallowEqualsRecords (
a: Record<string, unknown>,
b: Record<string, unknown>
): boolean {
const aKeys = Object.keys(a)
const bKeys = Object.keys(b)
if (aKeys.length !== bKeys.length) {
return false
}
if (aKeys.length === 0) {
return a === b
}
return aKeys.reduce((equals: boolean, key: string): boolean => {
return equals && a[key] === b[key]
}, true)
}
export default function shallowEquals (a: unknown, b: unknown): boolean {
if (a === b) {
return true
}
if (!a || !b) {
return false
}
if (a instanceof Date && b instanceof Date) {
return equalsDates(a, b)
}
return shallowEqualsRecords(
a as Record<string, unknown>,
b as Record<string, unknown>
)
}

View File

@ -1,5 +1,5 @@
import isUrl from 'is-url' import isUrl from 'is-url'
import { has, regexForFormat, shallowEqualObjects } from '@/utils' import { has, regexForFormat, shallowEquals } from '@/utils'
import { import {
ValidationContext, ValidationContext,
ValidationRuleFn, ValidationRuleFn,
@ -130,7 +130,7 @@ const rules: Record<string, ValidationRuleFn> = {
* Rule: Value is in an array (stack). * Rule: Value is in an array (stack).
*/ */
in ({ value }: ValidationContext, ...stack: any[]): boolean { in ({ value }: ValidationContext, ...stack: any[]): boolean {
return stack.some(item => typeof item === 'object' ? shallowEqualObjects(item, value) : item === value) return stack.some(item => typeof item === 'object' ? shallowEquals(item, value) : item === value)
}, },
/** /**
@ -198,7 +198,7 @@ const rules: Record<string, ValidationRuleFn> = {
* Rule: Value is not in stack. * Rule: Value is not in stack.
*/ */
not ({ value }: ValidationContext, ...stack: any[]): boolean { not ({ value }: ValidationContext, ...stack: any[]): boolean {
return !stack.some(item => typeof item === 'object' ? shallowEqualObjects(item, value) : item === value) return !stack.some(item => typeof item === 'object' ? shallowEquals(item, value) : item === value)
}, },
/** /**