veui
Version:
Baidu Enterprise UI for Vue.js.
116 lines (112 loc) • 3.32 kB
JavaScript
import { mergeWith, forEach } from 'lodash'
import { isTopMostOfType, wrapListeners, getModelEvent } from '../utils/helper'
import focusable from './focusable'
import { useFormChild } from '../components/Form/Form'
import { useFieldChild } from '../components/Form/Field'
import { useFacade } from '../components/Form/_facade'
export function useInput () {
return {
uiTypes: ['input'],
mixins: [
focusable,
useFacade((vm) => ({
getDeclaredName: () => vm.name,
// 内置校验
validate: () => {
return typeof vm.validate === 'function' ? vm.validate() : undefined
},
getModelEvent: () => getModelEvent(vm)
})),
useFormChild('form'),
useFieldChild('field', (vm) => {
if (vm.isTopMostInput) {
return vm.field.addInput(vm.getFacade())
}
})
],
props: {
name: String,
readonly: Boolean,
disabled: Boolean,
invalid: Boolean
},
data () {
return {
initialData: undefined,
isTopMostInput: isTopMostOfType(this, 'input', 'form-field')
}
},
computed: {
realName () {
return this.name || (this.field && this.field.getName())
},
realDisabled () {
return Boolean(
this.disabled ||
(this.field && this.field.isDisabled()) ||
(this.form && this.form.isDisabled()) // 可能不在 field 中,而直接在 form 中
)
},
realReadonly () {
return Boolean(
this.readonly ||
(this.field && this.field.isReadonly()) ||
(this.form && this.form.isReadonly()) // 可能不在 field 中,而直接在 form 中
)
},
realInvalid () {
return Boolean(
this.invalid ||
(this.field &&
this.field.isInvalid(this.getFacade()) &&
this.isTopMostInput)
)
},
isUnderField () {
return this.field && this.field.getName() && this.isTopMostInput
},
listenersFromField () {
return this.field
? this.field.getInteractiveListeners(this.getFacade())
: {}
},
listenersWithValidations () {
// 为啥要 wrap listeners: 避免 $listener 和 field/form 上交互事件合并时导致无限递归
let listeners = wrapListeners(this.$listeners)
if (this.isUnderField && Object.keys(this.listenersFromField).length) {
return mergeWith(listeners, this.listenersFromField, (a, b) =>
[].concat(a || [], b || [])
)
}
return listeners
}
},
created () {
if (!this.isUnderField) {
return
}
this.$watch(
() => this.listenersFromField,
this.applyValidationListeners,
{
immediate: true
}
)
},
methods: {
applyValidationListeners (val = {}, prev = {}) {
forEach(prev, (listener, eventName) => {
if (val[eventName] !== listener) {
this.$off(eventName, listener)
}
})
forEach(val, (listener, eventName) => {
if (prev[eventName] !== listener) {
this.$on(eventName, listener)
}
})
}
}
}
}
export default useInput()