refactor(form): support vue3

This commit is contained in:
07akioni 2020-10-06 23:23:36 +08:00
parent f601fc397d
commit 828c65e285
21 changed files with 185 additions and 146 deletions

View File

@ -29,7 +29,7 @@
>
<n-input
placeholder="Name"
@keydown.enter.native.prevent
@keydown.enter.prevent
v-model="model.dynamicInputValue[index].name"
/>
<!--
@ -44,7 +44,7 @@
>
<n-input
placeholder="Value"
@keydown.enter.native.prevent
@keydown.enter.prevent
v-model="model.dynamicInputValue[index].value"
/>
</n-form-item>

View File

@ -26,7 +26,7 @@
>
<n-input
placeholder="Name"
@keydown.enter.native.prevent
@keydown.enter.prevent
v-model="model.dynamicInputValue[index].name"
/>
<!--
@ -41,7 +41,7 @@
>
<n-input
placeholder="Value"
@keydown.enter.native.prevent
@keydown.enter.prevent
v-model="model.dynamicInputValue[index].value"
/>
</n-form-item>

View File

@ -12,7 +12,7 @@ Sometimes builtin triggers don't meet you demand. You can custom you valiation b
>
<n-input
v-model="model.age"
@keydown.enter.native.prevent
@keydown.enter.prevent
/>
</n-form-item-row>
<n-form-item-row
@ -23,7 +23,7 @@ Sometimes builtin triggers don't meet you demand. You can custom you valiation b
v-model="model.password"
@input="handlePasswordInput"
type="password"
@keydown.enter.native.prevent
@keydown.enter.prevent
/>
</n-form-item-row>
<n-form-item-row
@ -36,7 +36,7 @@ Sometimes builtin triggers don't meet you demand. You can custom you valiation b
:disabled="!model.password"
v-model="model.reenteredPassword"
type="password"
@keydown.enter.native.prevent
@keydown.enter.prevent
/>
</n-form-item-row>
<n-row :gutter="[0, 24]">

View File

@ -11,25 +11,25 @@
label="Name"
path="user.name"
>
<n-input v-model="formValue.user.name" placeholder="Input Name" />
<n-input v-model:value="formValue.user.name" placeholder="Input Name" />
</n-form-item>
<n-form-item
label="Age"
path="user.age"
>
<n-input placeholder="Input Age" v-model="formValue.user.age"/>
<n-input placeholder="Input Age" v-model:value="formValue.user.age"/>
</n-form-item>
<n-form-item
label="Adress"
path="user.address"
>
<n-input placeholder="Input Address" v-model="formValue.user.address"/>
<n-input placeholder="Input Address" v-model:value="formValue.user.address"/>
</n-form-item>
<n-form-item
label="Phone"
path="phone"
>
<n-input placeholder="Phone Number" v-model="formValue.phone"/>
<n-input placeholder="Phone Number" v-model:value="formValue.phone"/>
</n-form-item>
<n-form-item>
<n-button @click="handleValidateClick">Validate</n-button>
@ -42,6 +42,7 @@
```
```js
export default {
inject: ['message'],
data () {
return {
formValue: {
@ -98,13 +99,12 @@ export default {
e.preventDefault()
this.$refs.form.validate(errors => {
if (!errors) {
this.$NMessage.success('Valid')
this.message.success('Valid')
} else {
this.$NMessage.error('Invalid')
this.message.error('Invalid')
console.log('errors', errors)
}
})
console.log('end')
}
}
}

View File

@ -11,8 +11,8 @@
label="年龄"
>
<n-input
v-model="model.age"
@keydown.enter.native.prevent
v-model:value="model.age"
@keydown.enter.prevent
/>
</n-form-item-row>
<n-form-item-row
@ -20,10 +20,10 @@
label="密码"
>
<n-input
v-model="model.password"
v-model:value="model.password"
@input="handlePasswordInput"
type="password"
@keydown.enter.native.prevent
@keydown.enter.prevent
/>
</n-form-item-row>
<n-form-item-row
@ -34,9 +34,9 @@
>
<n-input
:disabled="!model.password"
v-model="model.reenteredPassword"
v-model:value="model.reenteredPassword"
type="password"
@keydown.enter.native.prevent
@keydown.enter.prevent
/>
</n-form-item-row>
<n-row :gutter="[0, 24]">

View File

@ -8,7 +8,7 @@
:feedback="inputFeedback"
>
<n-input
v-model="inputValue"
v-model:value="inputValue"
clearable
/>
</n-form-item>
@ -18,7 +18,7 @@
:feedback="inputNumberFeedback"
>
<n-input-number
v-model="inputNumberValue"
v-model:value="inputNumberValue"
/>
</n-form-item>
<n-form-item
@ -27,8 +27,7 @@
:feedback="selectFeedback"
>
<n-select
debug
v-model="selectValue"
v-model:value="selectValue"
:options="selectOptions"
clearable
/>

View File

@ -34,7 +34,7 @@ validator-debug
|trigger|`string \| Array<string>`||
|message|`string`||
### Form Item Props
### FormItem Props
|名称|类型|默认值|说明|
|-|-|-|-|
|feedback|`string`|`null`|表项的反馈信息。不设为 `null` 时,会覆盖规则验证的结果|
@ -46,17 +46,16 @@ validator-debug
|label-style|`Object`|`{}`||
|label-width|`number \| string`|`null`|如果没有被设定,使用外层表单的 `label-width`|
|path|`string`|`null`|将值收集到外层表单 `model` 对象的路径|
|required|`boolean`|`false`|是否展示必填的星号。注意:一个 `required: true` 的规则比这个属性有更高的优先级 & 这个属性不会影响表单的验证。验证完全依赖于规则|
|rule|`FormItemRule \| Array<FormItemRule>`|`null`|验证表项的规则,它会被通过 `rule-path` 从外层表单获取的规则合并来作为表项的验证规则。推荐还是在外层表单设置所有规则|
|rule-path|`string`|`null`|从外层表单的 `rules` 对象获取规则的路径。如果没有设定,使用表项的 `path` 代替|
|show-require-mark|`boolean`|`true`|在表项是必填的时候是不是展示星号。如果没有被设定,使用外层 `n-form``show-require-mark`|
|show-require-mark|`boolean`|`true`|是否展示必填的星号。如果没有被设定,使用外层 `n-form``show-require-mark`|
|size|`'small' \| 'medium' \| 'large'`|`'medium'`||
|validation-status|`'error' \| 'success' \| 'warning' \| null`|`null`|表单的验证状态。不设为 `null`时,会覆盖规则验证的结果|
### Form Item Row Props
接受 Form Item & [Row](n-row#Row-Props) 所有的 Props。
### Form Item Col Props
接受 Form Item & [Col](n-row#Col-Props) 所有的 Props。
### FormItemRow Props
接受 FormItem & [Row](n-row#Row-Props) 所有的 Props。
### FormItemCol Props
接受 FormItem & [Col](n-row#Col-Props) 所有的 Props。
## Methods
### Form Methods
@ -72,7 +71,7 @@ validator-debug
|validate|`(validateCallback?: (errors?: Array<ValidationError>) => any, shouldRuleBeApplied?: FormItemRule => boolean) => Promise<void>`|验证表单。Promise rejection 的返回值类型是 `Array<ValidationError>`。|
|clearValidationEffect|`() => void`||
### Form Item, Form Item Row, Form Item Col Methods
### FormItem, FormItemRow, FormItemCol Methods
|名称|类型|说明|
|-|-|-|
|validate|`(options: { trigger?: string, callback?: (errors?: Array<ValidationError>) => any, shouldRuleBeApplied?: FormItemRule => boolean, options?: AsyncValidatorOptions }) => Promise<void>`|验证表项Promise rejection 的返回值类型是 `Array<ValidationError>`。如果设定 `trigger`,这一个表项全部的规则都会被使用。`shouldRuleBeApplied` 可以用来进一步过滤已经经过 `trigger` 筛选的规则|
@ -81,12 +80,12 @@ validator-debug
关于 AsyncValidatorOptions参考 <n-a href="https://github.com/yiminghe/async-validator">async-validator</n-a>
## Slots
### Form, Form Item, Form Item Row, Form Item Col Slots
### Form, FormItem, FormItemRow, FormItemCol Slots
|名称|参数|说明|
|-|-|-|
|default|`()`||
### Form Item, Form Item Row, Form Item Col Slots
### FormItem, FormItem Row, FormItemCol Slots
|名称|参数|说明|
|-|-|-|
|label|`()`||

View File

@ -1,6 +1,6 @@
# 标签左置
```html
<n-radio-group v-model="size" name="left-size" style="margin-bottom: 12px;">
<n-radio-group v-model:value="size" name="left-size" style="margin-bottom: 12px;">
<n-radio-button value="small"></n-radio-button>
<n-radio-button value="medium" ></n-radio-button>
<n-radio-button value="large"></n-radio-button>
@ -18,10 +18,10 @@
}"
>
<n-form-item-row label="Input" path="inputValue">
<n-input placeholder="Input" v-model="model.inputValue" />
<n-input placeholder="Input" v-model:value="model.inputValue" />
</n-form-item-row>
<n-form-item-row label="Textarea" path="textareaValue">
<n-input placeholder="Textarea" v-model="model.textareaValue" type="textarea"
<n-input placeholder="Textarea" v-model:value="model.textareaValue" type="textarea"
:autosize="{
minRows: 3,
maxRows: 5
@ -29,60 +29,60 @@
/>
</n-form-item-row>
<n-form-item-row label="Select" path="selectValue">
<n-select placeholder="Select" :options="generalOptions" v-model="model.selectValue"/>
<n-select placeholder="Select" :options="generalOptions" v-model:value="model.selectValue"/>
</n-form-item-row>
<n-form-item-row label="Multiple Select" path="multipleSelectValue">
<n-select placeholder="Select" :options="generalOptions" v-model="model.multipleSelectValue" multiple/>
<n-select placeholder="Select" :options="generalOptions" v-model:value="model.multipleSelectValue" multiple/>
</n-form-item-row>
<n-form-item-row label="Datetime" path="datetimeValue">
<n-date-picker type="datetime" v-model="model.datetimeValue"/>
<n-date-picker type="datetime" v-model:value="model.datetimeValue"/>
</n-form-item-row>
<n-form-item-row label="Switch" path="switchValue">
<n-switch v-model="model.switchValue" />
<n-switch v-model:value="model.switchValue" />
</n-form-item-row>
<n-form-item-row label="Checkbox Group" path="checkboxGroupValue">
<n-checkbox-group v-model="model.checkboxGroupValue">
<n-checkbox-group v-model:value="model.checkboxGroupValue">
<n-checkbox value="Option 1">Option 1</n-checkbox>
<n-checkbox value="Option 2">Option 2</n-checkbox>
<n-checkbox value="Option 3">Option 3</n-checkbox>
</n-checkbox-group>
</n-form-item-row>
<n-form-item-row label="Radio Group" path="radioGroupValue">
<n-radio-group v-model="model.radioGroupValue" name="radiogroup1">
<n-radio-group v-model:value="model.radioGroupValue" name="radiogroup1">
<n-radio value="Radio 1">Radio 1</n-radio>
<n-radio value="Radio 2">Radio 2</n-radio>
<n-radio value="Radio 3">Radio 3</n-radio>
</n-radio-group>
</n-form-item-row>
<n-form-item-row label="Radio Button Group" path="radioGroupValue">
<n-radio-group v-model="model.radioGroupValue" name="radiogroup2">
<n-radio-group v-model:value="model.radioGroupValue" name="radiogroup2">
<n-radio-button value="Radio 1">Radio 1</n-radio-button>
<n-radio-button value="Radio 2">Radio 2</n-radio-button>
<n-radio-button value="Radio 3">Radio 3</n-radio-button>
</n-radio-group>
</n-form-item-row>
<n-form-item-row label="Input Number" path="inputNumberValue">
<n-input-number v-model="model.inputNumberValue"/>
<n-input-number v-model:value="model.inputNumberValue"/>
</n-form-item-row>
<n-form-item-row label="Time Picker" path="timePickerValue">
<n-time-picker v-model="model.timePickerValue" />
<n-time-picker v-model:value="model.timePickerValue" />
</n-form-item-row>
<n-form-item-row label="Slider" path="sliderValue">
<n-slider v-model="model.sliderValue" :step="5"/>
<n-slider v-model:value="model.sliderValue" :step="5"/>
</n-form-item-row>
<n-form-item-row label="Transfer" path="transferValue">
<n-transfer
v-model="model.transferValue"
v-model:value="model.transferValue"
:options="generalOptions"
/>
</n-form-item-row>
<n-form-item-row :gutter="[28, 0]" label="Nested Path">
<n-row :gutter="[28, 0]" >
<n-form-item-col :span="12" path="nestedValue.path1">
<n-input placeholder="Nested Path 1" v-model="model.nestedValue.path1"/>
<n-input placeholder="Nested Path 1" v-model:value="model.nestedValue.path1"/>
</n-form-item-col>
<n-form-item-col :span="12" path="nestedValue.path2">
<n-select placeholder="Nested Path 2" :options="generalOptions" v-model="model.nestedValue.path2"/>
<n-select placeholder="Nested Path 2" :options="generalOptions" v-model:value="model.nestedValue.path2"/>
</n-form-item-col>
</n-row>
</n-form-item-row>
@ -102,6 +102,7 @@
```js
export default {
inject: ['message'],
data () {
return {
size: 'medium',
@ -216,10 +217,10 @@ export default {
e.preventDefault()
this.$refs.form.validate(errors => {
if (!errors) {
this.$NMessage.success('验证成功')
this.message.success('验证成功')
} else {
console.log(errors)
this.$NMessage.error('验证失败')
this.message.error('验证失败')
}
})
}

View File

@ -1,6 +1,6 @@
# 标签上置
```html
<n-radio-group v-model="size" name="top-size" style="margin-bottom: 12px;">
<n-radio-group v-model:value="size" name="top-size" style="margin-bottom: 12px;">
<n-radio-button value="small"></n-radio-button>
<n-radio-button value="medium" ></n-radio-button>
<n-radio-button value="large"></n-radio-button>
@ -14,10 +14,10 @@
>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Input" path="inputValue">
<n-input placeholder="Input" v-model="model.inputValue" />
<n-input placeholder="Input" v-model:value="model.inputValue" />
</n-form-item-col>
<n-form-item-col :span="12" label="Textarea" path="textareaValue">
<n-input placeholder="Textarea" v-model="model.textareaValue" type="textarea"
<n-input placeholder="Textarea" v-model:value="model.textareaValue" type="textarea"
:autosize="{
minRows: 3,
maxRows: 5
@ -27,30 +27,30 @@
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Select" path="selectValue">
<n-select placeholder="Select" :options="generalOptions" v-model="model.selectValue"/>
<n-select placeholder="Select" :options="generalOptions" v-model:value="model.selectValue"/>
</n-form-item-col>
<n-form-item-col :span="12" label="Multiple Select" path="multipleSelectValue">
<n-select placeholder="Select" :options="generalOptions" v-model="model.multipleSelectValue" multiple/>
<n-select placeholder="Select" :options="generalOptions" v-model:value="model.multipleSelectValue" multiple/>
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Datetime" path="datetimeValue">
<n-date-picker type="datetime" v-model="model.datetimeValue"/>
<n-date-picker type="datetime" v-model:value="model.datetimeValue"/>
</n-form-item-col>
<n-form-item-col :span="12" label="Switch" path="switchValue">
<n-switch v-model="model.switchValue" />
<n-switch v-model:value="model.switchValue" />
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Checkbox Group" path="checkboxGroupValue">
<n-checkbox-group v-model="model.checkboxGroupValue">
<n-checkbox-group v-model:value="model.checkboxGroupValue">
<n-checkbox value="Option 1">Option 1</n-checkbox>
<n-checkbox value="Option 2">Option 2</n-checkbox>
<n-checkbox value="Option 3">Option 3</n-checkbox>
</n-checkbox-group>
</n-form-item-col>
<n-form-item-col :span="12" label="Radio Group" path="radioGroupValue">
<n-radio-group v-model="model.radioGroupValue" name="radiogroup1">
<n-radio-group v-model:value="model.radioGroupValue" name="radiogroup1">
<n-radio value="Radio 1">Radio 1</n-radio>
<n-radio value="Radio 2">Radio 2</n-radio>
<n-radio value="Radio 3">Radio 3</n-radio>
@ -59,37 +59,37 @@
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Radio Button Group" path="radioGroupValue">
<n-radio-group v-model="model.radioGroupValue" name="radiogroup2">
<n-radio-group v-model:value="model.radioGroupValue" name="radiogroup2">
<n-radio-button value="Radio 1">Radio 1</n-radio-button>
<n-radio-button value="Radio 2">Radio 2</n-radio-button>
<n-radio-button value="Radio 3">Radio 3</n-radio-button>
</n-radio-group>
</n-form-item-col>
<n-form-item-col :span="12" label="Input Number" path="inputNumberValue">
<n-input-number v-model="model.inputNumberValue"/>
<n-input-number v-model:value="model.inputNumberValue"/>
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="12" label="Time Picker" path="timePickerValue">
<n-time-picker v-model="model.timePickerValue" />
<n-time-picker v-model:value="model.timePickerValue" />
</n-form-item-col>
<n-form-item-col :span="12" label="Slider" path="sliderValue">
<n-slider v-model="model.sliderValue" :step="5"/>
<n-slider v-model:value="model.sliderValue" :step="5"/>
</n-form-item-col>
</n-row>
<n-row :gutter="24">
<n-form-item-col :span="14" label="Transfer" path="transferValue">
<n-transfer
style="width: 100%;"
v-model="model.transferValue"
v-model:value="model.transferValue"
:options="generalOptions"
/>
</n-form-item-col>
<n-form-item-col :span="5" label="Nested Path" path="nestedValue.path1">
<n-cascader placeholder="Nested Path 1" v-model="model.nestedValue.path1" :options="cascaderOptions"/>
<n-cascader placeholder="Nested Path 1" v-model:value="model.nestedValue.path1" :options="cascaderOptions"/>
</n-form-item-col>
<n-form-item-col :span="5" path="nestedValue.path2">
<n-select placeholder="Nested Path 2" :options="generalOptions" v-model="model.nestedValue.path2"/>
<n-select placeholder="Nested Path 2" :options="generalOptions" v-model:value="model.nestedValue.path2"/>
</n-form-item-col>
</n-row>
<n-row>

View File

@ -9,14 +9,16 @@ export default function createDemoRouter (app, routes) {
})
router.beforeEach(function (to, from, next) {
if (loadingBarApiRef.value) {
loadingBarApiRef.value.start()
if (!from || to.path !== from.path) {
if (loadingBarApiRef.value) {
loadingBarApiRef.value.start()
}
}
next()
})
router.afterEach(function (to, from) {
if (to.path !== from.path) {
if (!from || to.path !== from.path) {
if (loadingBarApiRef.value) {
loadingBarApiRef.value.finish()
}

View File

@ -4,10 +4,8 @@ export default function (options = {}) {
mergedSize
} = options
return {
provide () {
return {
NFormItem: null
}
provide: {
NFormItem: null
},
inject: {
NFormItem: {

View File

@ -95,6 +95,7 @@ export default {
) {
return NFormItem.mergedSize
}
return 'medium'
}
}),
usecssr(styles)
@ -104,7 +105,7 @@ export default {
validator (value) {
return ['small', 'medium', 'large'].includes(value)
},
default: null
default: undefined
},
value: {
type: [Number, Boolean, String],

View File

@ -22,7 +22,7 @@ export default {
validator (value) {
return ['small', 'medium', 'large'].includes(value)
},
default: null
default: undefined
},
value: {
type: Array,

View File

@ -45,16 +45,20 @@ export default {
type: Object,
default: undefined
},
showRequireMark: {
type: Boolean,
default: undefined
},
size: {
validator (value) {
return ['small', 'medium', 'large'].includes(value)
},
default: undefined
},
showRequireMark: {
type: Boolean,
default: undefined
},
showFeedback: {
type: Boolean,
default: true
},
onSubmit: {
type: Function,
default: e => e.preventDefault()

View File

@ -32,16 +32,17 @@
<slot />
</div>
<div
v-if="mergedValidationStatus !== undefined || path"
v-if="mergedShowFeedback"
:key="feedbackId"
class="n-form-item-feedback-wrapper"
>
<transition
name="n-form-item-feedback-transition"
@before-enter="handleBeforeEnter"
@before-leave="handleBeforeLeave"
@after-leave="handleAfterLeave"
>
<div v-if="feedback !== undefined" class="n-form-item-feedback">
<div
v-if="feedback !== undefined && feedback !== null"
class="n-form-item-feedback"
>
{{ feedback }}
</div>
<div v-else-if="explains.length" class="n-form-item-feedback">
@ -68,6 +69,7 @@ import {
} from '../../_mixins'
import styles from './styles'
import { warn } from '../../_utils/naive'
import { createId } from '../../_utils/vue'
import {
formItemMisc,
formItemSize,
@ -158,6 +160,10 @@ export default {
type: Boolean,
default: undefined
},
showFeedback: {
type: Boolean,
default: undefined
},
rule: {
type: [Object, Array],
default: undefined
@ -186,9 +192,6 @@ export default {
inject: {
NForm: {
default: null
},
NFormItem: {
default: null
}
},
provide () {
@ -206,7 +209,7 @@ export default {
data () {
return {
explains: [],
feedbackTransitionDisabled: true
feedbackId: createId()
}
},
watch: {
@ -215,28 +218,11 @@ export default {
this.restoreValidation()
}
},
mounted () {
this.feedbackTransitionDisabled = false
},
methods: {
restoreValidation () {
this.explains = []
this.validationErrored = false
this.disableFeedbackTransition()
},
handleBeforeLeave (feedback) {
if (this.feedbackTransitionDisabled) {
if (feedback) {
feedback.style.transition = 'none'
}
} else {
if (feedback) {
feedback.style.transition = null
}
}
},
disableFeedbackTransition () {
this.feedbackTransitionDisabled = true
this.feedbackId = createId()
},
handleContentBlur () {
this._validate('blur')
@ -295,9 +281,6 @@ export default {
* be valid.
*/
if (!path) {
if (__DEV__) {
warn('form-item', '`n-form-item` without `path` can\'t be validated.')
}
return Promise.resolve({
valid: true
})
@ -357,12 +340,6 @@ export default {
clearValidationEffect () {
this.explains = []
this.validationErrored = false
},
handleBeforeEnter () {
this.feedbackTransitionDisabled = false
},
handleAfterLeave () {
this.feedbackTransitionDisabled = false
}
}
}

View File

@ -70,13 +70,22 @@ export function formItemMisc (props) {
if (validationErroredRef.value) return 'error'
return undefined
})
const mergedShowFeedbackRef = computed(() => {
const {
showFeedback
} = props
if (showFeedback) return showFeedback
if (NForm && NForm.showFeedback) return NForm.showFeedback
return true
})
return {
validationErrored: validationErroredRef,
mergedLabelStyle: mergedLabelStyleRef,
mergedLabelPlacement: mergedLabelPlacementRef,
mergedLabelAlign: mergedLabelAlignRef,
mergedShowRequireMark: mergedShowRequireMarkRef,
mergedValidationStatus: mergedValidationStatusRef
mergedValidationStatus: mergedValidationStatusRef,
mergedShowFeedback: mergedShowFeedbackRef
}
}

View File

@ -63,10 +63,12 @@
import NIcon from '../../icon/index'
import RemoveIcon from '../../_icons/remove-outline.vue'
import AddIcon from '../../_icons/add-outline.vue'
import themeable from '../../_mixins/themeable'
import withapp from '../../_mixins/withapp'
import asformitem from '../../_mixins/asformitem'
import usecssr from '../../_mixins/usecssr'
import {
configurable,
themeable,
asformitem,
usecssr
} from '../../_mixins'
import { warn } from '../../_utils/naive/warn'
import styles from './styles'
@ -93,16 +95,11 @@ export default {
AddIcon
},
mixins: [
withapp,
configurable,
themeable,
asformitem(),
usecssr(styles)
],
inject: {
NFormItem: {
default: null
}
},
props: {
placeholder: {
type: String,

View File

@ -68,6 +68,7 @@ export default {
) {
return NFormItem.mergedSize
}
return 'medium'
}
}),
radioMixin

View File

@ -6,6 +6,8 @@
}"
:tabindex="!disabled ? 0 : false"
@click="handleClick"
@focus="handleFocus"
@blur="handleBlur"
>
<div
class="n-switch__rail"
@ -18,25 +20,28 @@
</template>
<script>
import withapp from '../../_mixins/withapp'
import themeable from '../../_mixins/themeable'
import asformitem from '../../_mixins/asformitem'
import usecssr from '../../_mixins/usecssr'
import {
configurable,
themeable,
asformitem,
usecssr
} from '../../_mixins'
import {
call
} from '../../_utils/vue'
import {
warn
} from '../../_utils/naive'
import styles from './styles'
export default {
cssrName: 'Switch',
mixins: [
withapp,
configurable,
themeable,
asformitem(),
usecssr(styles)
],
inject: {
NFormItem: {
default: null
}
},
props: {
value: {
type: Boolean,
@ -48,17 +53,56 @@ export default {
},
// eslint-disable-next-line vue/prop-name-casing
'onUpdate:value': {
type: Function,
default: () => {}
type: [Function, Array],
default: undefined
},
onChange: {
validator () {
if (__DEV__) warn('switch', '`on-change` is deprecated, please use `on-update:value` instead.')
return true
},
default: undefined
}
},
methods: {
doUpdateValue (...args) {
const {
'onUpdate:value': onUpdateValue,
onChange,
__triggerFormInput,
__triggerFormChange
} = this
if (onUpdateValue) call(onUpdateValue, ...args)
if (onChange) call(onChange, ...args)
__triggerFormInput()
__triggerFormChange()
},
doFocus (...args) {
const {
onFocus,
__triggerFormFocus
} = this
if (onFocus) call(onFocus, ...args)
__triggerFormFocus()
},
doBlur (...args) {
const {
onBlur,
__triggerFormBlur
} = this
if (onBlur) call(onBlur, ...args)
__triggerFormBlur()
},
handleClick () {
if (!this.disabled) {
this['onUpdate:value'](!this.value)
this.__triggerFormInput()
this.__triggerFormChange()
this.doUpdateValue(!this.value)
}
},
handleFocus (e) {
this.doFocus(e)
},
handleBlur (e) {
this.doBlur(e)
}
}
}

View File

@ -79,7 +79,9 @@
</div>
</n-scrollbar>
</template>
<n-empty v-else />
<transition name="n-fade-in-transition" :appear="isMounted">
<n-empty v-if="!filteredSrcOpts.length" />
</transition>
</div>
</div>
<div class="n-transfer-list__border-mask" />
@ -165,7 +167,9 @@
</div>
</n-scrollbar>
</template>
<n-empty v-else />
<transition name="n-fade-in-transition" :appear="isMounted">
<n-empty v-if="!filteredTgtOpts.length" />
</transition>
</div>
</div>
<div class="n-transfer-list__border-mask" />

View File

@ -1,5 +1,6 @@
import { c, cTB, cB, cE, cM } from '../../../../_utils/cssr'
import animationStyle from './animation.cssr.js'
import fadeInTransition from '../../../../_styles/transitions/fade-in.js'
export default c([
({ props }) => {
@ -139,7 +140,9 @@ export default c([
left: '50%',
top: '50%',
transform: 'translateY(-50%) translateX(-50%)'
}),
}, [
fadeInTransition()
]),
cB('transfer-list-content', {
padding: 0,
margin: 0,