refactor: use asformitem instead of emitter mixin

This commit is contained in:
07akioni 2019-11-07 21:35:26 +08:00
parent 986ecb3de4
commit 23eda5b40c
13 changed files with 58 additions and 88 deletions

View File

@ -11,14 +11,18 @@
<n-row> <n-row>
<n-col :span="24"> <n-col :span="24">
<n-form-item path="password" label="Password"> <n-form-item path="password" label="Password">
<n-input v-model="model.password" @input="handlePasswordInput"/> <n-input v-model="model.password" @input="handlePasswordInput" type="password"/>
</n-form-item> </n-form-item>
</n-col> </n-col>
</n-row> </n-row>
<n-row> <n-row>
<n-col :span="24"> <n-col :span="24">
<n-form-item path="reenteredPassword" label="Re-enter Password" ref="reenteredPassword"> <n-form-item
<n-input v-model="model.reenteredPassword"/> path="reenteredPassword"
label="Re-enter Password"
ref="reenteredPassword"
>
<n-input v-model="model.reenteredPassword" type="password"/>
</n-form-item> </n-form-item>
</n-col> </n-col>
</n-row> </n-row>
@ -48,16 +52,16 @@ export default {
age: [ age: [
{ {
validator (rule, value) { validator (rule, value) {
return /\d+/.test(value) return /^\d*$/.test(value)
}, },
message: 'Age should be an integer', message: 'Please input an integer',
trigger: 'input' trigger: 'input'
}, },
{ {
validator (rule, value) { validator (rule, value) {
return Number(value) > 18 return Number(value) > 18
}, },
message: 'Age should be greater than 18', message: 'Age should be above 18',
trigger: 'input' trigger: 'input'
} }
], ],
@ -70,7 +74,7 @@ export default {
{ {
validator: this.validatePasswordSame, validator: this.validatePasswordSame,
message: 'Password is not same as re-entered password!', message: 'Password is not same as re-entered password!',
trigger: 'blur' trigger: ['blur', 'password-input']
}, },
{ {
required: true, required: true,
@ -82,7 +86,9 @@ export default {
}, },
methods: { methods: {
handlePasswordInput () { handlePasswordInput () {
this.$refs.reenteredPassword.validate('input') if (this.model.reenteredPassword) {
this.$refs.reenteredPassword.validate('password-input')
}
}, },
handleValidateButtonClick (e) { handleValidateButtonClick (e) {
e.preventDefault() e.preventDefault()

View File

@ -1,8 +1,12 @@
<script> <script>
import asformitem from '../../../mixins/asformitem'
export default { export default {
name: 'NCheckboxGroup', name: 'NCheckboxGroup',
mixins: [ asformitem() ],
provide () { provide () {
return { return {
NFormItem: null,
NCheckboxGroup: this NCheckboxGroup: this
} }
}, },

View File

@ -36,6 +36,7 @@
import withapp from '../../../mixins/withapp' import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable' import themeable from '../../../mixins/themeable'
import hollowoutable from '../../../mixins/hollowoutable' import hollowoutable from '../../../mixins/hollowoutable'
import asformitem from '../../../mixins/asformitem'
import CheckMark from './CheckMark' import CheckMark from './CheckMark'
import LineMark from './LineMark' import LineMark from './LineMark'
import collectable from '../../../mixins/collectable' import collectable from '../../../mixins/collectable'
@ -55,6 +56,7 @@ export default {
withapp, withapp,
themeable, themeable,
hollowoutable, hollowoutable,
asformitem(),
collectable('NCheckboxGroup', 'collectedCheckboxValues') collectable('NCheckboxGroup', 'collectedCheckboxValues')
], ],
model: { model: {

View File

@ -41,7 +41,7 @@
</div> </div>
</template> </template>
<script> <script>
import AsyncValidator from 'async-validator' import Schema from 'async-validator'
import get from 'lodash/get' import get from 'lodash/get'
import registerable from '../../../mixins/registerable' import registerable from '../../../mixins/registerable'
import withapp from '../../../mixins/withapp' import withapp from '../../../mixins/withapp'
@ -75,6 +75,10 @@ export default {
type: String, type: String,
default: null default: null
}, },
first: {
type: Boolean,
default: false
},
rulePath: { rulePath: {
type: String, type: String,
default: null default: null
@ -192,10 +196,15 @@ export default {
handleContentInput () { handleContentInput () {
this.validate('input') this.validate('input')
}, },
validate (trigger = null) { validate (trigger = null, options = null) {
if (!this.path) { if (!this.path) {
return return
} }
if (!options) {
options = {}
options.first = this.first
options.supressWarning = this.supressWarning
}
const rules = this.synthesizedRules const rules = this.synthesizedRules
const path = this.path const path = this.path
const value = get(this.NForm.model, this.path, null) const value = get(this.NForm.model, this.path, null)
@ -207,8 +216,8 @@ export default {
} }
}) })
if (!activeRules.length) return if (!activeRules.length) return
const validator = new AsyncValidator({ [path]: activeRules }) const validator = new Schema({ [path]: activeRules })
validator.validate({ [path]: value }, {}, (errors, fields) => { validator.validate({ [path]: value }, options, (errors, fields) => {
// console.log('validate', errors, fields) // console.log('validate', errors, fields)
if (errors && errors.length) { if (errors && errors.length) {
this.explains = errors.map(error => error.message) this.explains = errors.map(error => error.message)

View File

@ -134,7 +134,12 @@ export default {
components: { components: {
NCancelMark NCancelMark
}, },
mixins: [ withapp, themeable, asformitem() ], mixins: [ withapp, themeable, asformitem({
change: 'change',
blur: 'blur',
focus: 'focus',
input: 'input'
})],
props: { props: {
type: { type: {
type: String, type: String,

View File

@ -49,9 +49,9 @@
<script> <script>
import NIcon from '../../Icon/index' import NIcon from '../../Icon/index'
import Emitter from '../../../mixins/emitter'
import themeable from '../../../mixins/themeable' import themeable from '../../../mixins/themeable'
import withapp from '../../../mixins/withapp' import withapp from '../../../mixins/withapp'
import asformitem from '../../../mixins/asformitem'
import mdRemove from '../../../icons/md-remove' import mdRemove from '../../../icons/md-remove'
import mdAdd from '../../../icons/md-add' import mdAdd from '../../../icons/md-add'
@ -77,7 +77,7 @@ export default {
mdRemove, mdRemove,
mdAdd mdAdd
}, },
mixins: [ withapp, themeable, Emitter ], mixins: [ withapp, themeable, asformitem() ],
inject: { inject: {
NFormItem: { NFormItem: {
default: null default: null
@ -161,7 +161,6 @@ export default {
const adjustedValue = this.adjustValue(newValue) const adjustedValue = this.adjustValue(newValue)
if (adjustedValue === newValue) { if (adjustedValue === newValue) {
this.$emit('change', newValue, oldValue) this.$emit('change', newValue, oldValue)
this.formBlur('change', newValue)
} else { } else {
this.$emit('input', adjustedValue) this.$emit('input', adjustedValue)
} }
@ -174,11 +173,6 @@ export default {
} }
e.preventDefault() e.preventDefault()
}, },
formBlur (type, val) {
if (this.NFormItem) {
this.dispatch('NFormItem', 'on-form-' + type, val)
}
},
handleFocus (e) { handleFocus (e) {
this.$emit('focus', e, this.value) this.$emit('focus', e, this.value)
}, },
@ -234,7 +228,6 @@ export default {
e.target.value = value e.target.value = value
this.$emit('input', value) this.$emit('input', value)
this.$emit('blur', e, value) this.$emit('blur', e, value)
this.formBlur('blur', value)
} }
} }
} }

View File

@ -2,26 +2,12 @@
import withapp from '../../../mixins/withapp' import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable' import themeable from '../../../mixins/themeable'
import hollowoutable from '../../../mixins/hollowoutable' import hollowoutable from '../../../mixins/hollowoutable'
import asformitem from '../../../mixins/asformitem'
function mapSlot (h, defaultSlot, currentComponent) { function mapSlot (h, defaultSlot, currentComponent) {
/**
* connect current component's v-model to child instance
*/
// const wrapInstance = instance => {
// if (instance.componentOptions.tag === 'n-radio' || instance.componentOptions.tag === 'n-radio-button') {
// instance.componentOptions.propsData.privateValue = currentComponent.value
// instance.componentOptions.listeners = {
// ...instance.componentOptions.listeners,
// input: (v) => {
// currentComponent.$emit('input', v)
// }
// }
// return instance
// } else return null
// }
const mappedSlot = [] const mappedSlot = []
for (let i = 0; i < defaultSlot.length; ++i) { for (let i = 0; i < defaultSlot.length; ++i) {
const wrappedInstance = defaultSlot[i] // wrapInstance(defaultSlot[i]) const wrappedInstance = defaultSlot[i]
if (wrappedInstance === null) { if (wrappedInstance === null) {
console.error('[naive ui]: Please don\'t use tags other than `n-radio` and `n-radio-button` in `n-radio-group`.') console.error('[naive ui]: Please don\'t use tags other than `n-radio` and `n-radio-button` in `n-radio-group`.')
continue continue
@ -34,7 +20,6 @@ function mapSlot (h, defaultSlot, currentComponent) {
const lastInstanceDisabled = lastInstanceComponentOptions.propsData.disabled const lastInstanceDisabled = lastInstanceComponentOptions.propsData.disabled
const currentInstanceChecked = currentComponent.$props.value === wrappedInstance.componentOptions.propsData.value const currentInstanceChecked = currentComponent.$props.value === wrappedInstance.componentOptions.propsData.value
const currentInstanceDisabled = wrappedInstance.componentOptions.propsData.disabled const currentInstanceDisabled = wrappedInstance.componentOptions.propsData.disabled
let lastInstancePriority let lastInstancePriority
let currentInstancePriority let currentInstancePriority
if (currentComponent.synthesizedTheme === 'dark') { if (currentComponent.synthesizedTheme === 'dark') {
@ -82,7 +67,7 @@ function mapSlot (h, defaultSlot, currentComponent) {
export default { export default {
name: 'NRadioGroup', name: 'NRadioGroup',
mixins: [withapp, themeable, hollowoutable], mixins: [withapp, themeable, hollowoutable, asformitem()],
provide () { provide () {
return { return {
NRadioGroup: this NRadioGroup: this

View File

@ -23,13 +23,13 @@
</template> </template>
<script> <script>
import Emitter from '../../../mixins/emitter' import asformitem from '../../../mixins/asformitem'
import withapp from '../../../mixins/withapp' import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable' import themeable from '../../../mixins/themeable'
export default { export default {
name: 'NRadio', name: 'NRadio',
mixins: [ withapp, themeable, Emitter ], mixins: [ withapp, themeable, asformitem() ],
model: { model: {
prop: 'privateValue', prop: 'privateValue',
event: 'input' event: 'input'
@ -37,9 +37,6 @@ export default {
inject: { inject: {
NRadioGroup: { NRadioGroup: {
default: null default: null
},
NFormItem: {
default: null
} }
}, },
props: { props: {
@ -65,6 +62,11 @@ export default {
} }
} }
}, },
watch: {
value (value, oldValue) {
this.$emit('change', value, oldValue)
}
},
methods: { methods: {
handleKeyUpEnter () { handleKeyUpEnter () {
this.toggle() this.toggle()
@ -77,9 +79,6 @@ export default {
if (this.disabled) return if (this.disabled) return
if (this.privateValue !== this.value) { if (this.privateValue !== this.value) {
this.emitValue('input', this.value) this.emitValue('input', this.value)
if (this.NFormItem) {
this.dispatch('NFormItem', 'form-item-change', this.value)
}
} }
}, },
emitValue () { emitValue () {

View File

@ -94,6 +94,7 @@ import detachable from '../../../mixins/detachable'
import placeable from '../../../mixins/placeable' import placeable from '../../../mixins/placeable'
import withapp from '../../../mixins/withapp' import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable' import themeable from '../../../mixins/themeable'
import asformitem from '../../../mixins/asformitem'
function handleFirstHandleMouseMove (e) { function handleFirstHandleMouseMove (e) {
const railRect = this.$refs.rail.getBoundingClientRect() const railRect = this.$refs.rail.getBoundingClientRect()
@ -117,7 +118,7 @@ function handleSecondHandleMouseMove (e) {
export default { export default {
name: 'NSlider', name: 'NSlider',
mixins: [withapp, themeable, hollowoutable, detachable, placeable], mixins: [withapp, themeable, hollowoutable, detachable, placeable, asformitem()],
props: { props: {
marks: { marks: {
type: Object, type: Object,

View File

@ -15,13 +15,13 @@
</template> </template>
<script> <script>
import Emitter from '../../../mixins/emitter'
import withapp from '../../../mixins/withapp' import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable' import themeable from '../../../mixins/themeable'
import asformitem from '../../../mixins/asformitem'
export default { export default {
name: 'NSwitch', name: 'NSwitch',
mixins: [ withapp, themeable, Emitter ], mixins: [ withapp, themeable, asformitem() ],
inject: { inject: {
NFormItem: { NFormItem: {
default: null default: null
@ -46,9 +46,6 @@ export default {
handleClick () { handleClick () {
if (!this.disabled) { if (!this.disabled) {
this.$emit('input', !this.value) this.$emit('input', !this.value)
if (this.NFormItem) {
this.dispatch('NFormItem', 'form-item-change', !this.value)
}
} }
} }
} }

View File

@ -138,6 +138,7 @@ import clickoutside from '../../../directives/clickoutside'
import zindexable from '../../../mixins/zindexable' import zindexable from '../../../mixins/zindexable'
import withapp from '../../../mixins/withapp' import withapp from '../../../mixins/withapp'
import themeable from '../../../mixins/themeable' import themeable from '../../../mixins/themeable'
import asformitem from '../../../mixins/asformitem'
import isValid from 'date-fns/isValid' import isValid from 'date-fns/isValid'
import startOfSecond from 'date-fns/startOfSecond' import startOfSecond from 'date-fns/startOfSecond'
import startOfMinute from 'date-fns/startOfMinute' import startOfMinute from 'date-fns/startOfMinute'
@ -194,7 +195,7 @@ export default {
directives: { directives: {
clickoutside clickoutside
}, },
mixins: [detachable, placeable, zindexable, withapp, themeable], mixins: [detachable, placeable, zindexable, withapp, themeable, asformitem()],
props: { props: {
placement: { placement: {
type: String, type: String,

View File

@ -1,8 +1,7 @@
export default function (events = { export default function (events = {
change: 'change', change: 'change',
blur: 'blur', blur: 'blur',
focus: 'focus', focus: 'focus'
input: 'input'
}) { }) {
return { return {
inject: { inject: {

View File

@ -1,31 +0,0 @@
function broadcast (componentName, eventName, params) {
this.$children.forEach(child => {
let name = child.$options.name
if (name === componentName) {
child.$emit.apply(child, [eventName].concat(params))
} else {
broadcast.apply(child, [componentName, eventName].concat([params]))
}
})
}
export default {
methods: {
dispatch (componentName, eventName, params) {
let parent = this.$parent || this.$root
let name = parent.$options.name
while (parent && (!name || name !== componentName)) {
parent = parent.$parent
if (parent) {
name = parent.$options.name
}
}
if (parent) {
parent.$emit.apply(parent, [eventName].concat(params))
}
},
broadcast (componentName, eventName, params) {
broadcast.call(this, componentName, eventName, params)
}
}
}