feat: migrate Field component

This commit is contained in:
chenjiahan 2020-07-26 13:06:40 +08:00
parent 6f6aaeea87
commit 75421a4727
5 changed files with 87 additions and 92 deletions

View File

@ -8,6 +8,7 @@
- Popup: `v-model` 重命名为 `v-model:show` - Popup: `v-model` 重命名为 `v-model:show`
- ShareSheet: `v-model` 重命名为 `v-model:show` - ShareSheet: `v-model` 重命名为 `v-model:show`
- ActionSheet: `v-model` 重命名为 `v-model:show` - ActionSheet: `v-model` 重命名为 `v-model:show`
- Field: v-model 对应的属性 `value` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue`
- Switch: v-model 对应的属性 `value` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue` - Switch: v-model 对应的属性 `value` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue`
- Sidebar: v-model 对应的属性 `activeKey` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue` - Sidebar: v-model 对应的属性 `activeKey` 重命名为 `modelValue`,事件由 `input` 重命名为 `update:modelValue`
- TreeSelect: `active-id.sync` 重命名为 `v-model:active-id` - TreeSelect: `active-id.sync` 重命名为 `v-model:active-id`

View File

@ -2,6 +2,7 @@
module.exports = [ module.exports = [
'button', 'button',
'cell', 'cell',
'cell-group',
'icon', 'icon',
'info', 'info',
'image', 'image',
@ -35,4 +36,5 @@ module.exports = [
'notice-bar', 'notice-bar',
'share-sheet', 'share-sheet',
'pull-refresh', 'pull-refresh',
'field',
]; ];

View File

@ -1,7 +1,7 @@
<template> <template>
<demo-block :title="t('disabled')"> <demo-block :title="t('disabled')">
<van-field :value="t('inputReadonly')" :label="t('text')" readonly /> <van-field :model-value="t('inputReadonly')" :label="t('text')" readonly />
<van-field :value="t('inputDisabled')" :label="t('text')" disabled /> <van-field :model-value="t('inputDisabled')" :label="t('text')" disabled />
</demo-block> </demo-block>
</template> </template>

View File

@ -53,10 +53,6 @@ export default createComponent({
errorMessage: String, errorMessage: String,
errorMessageAlign: String, errorMessageAlign: String,
showWordLimit: Boolean, showWordLimit: Boolean,
value: {
type: [String, Number],
default: '',
},
type: { type: {
type: String, type: String,
default: 'text', default: 'text',
@ -69,6 +65,10 @@ export default createComponent({
type: Boolean, type: Boolean,
default: null, default: null,
}, },
modelValue: {
type: [String, Number],
default: '',
},
clearTrigger: { clearTrigger: {
type: String, type: String,
default: 'focus', default: 'focus',
@ -79,6 +79,18 @@ export default createComponent({
}, },
}, },
emits: [
'blur',
'focus',
'clear',
'click',
'keypress',
'click-input',
'click-left-icon',
'click-right-icon',
'update:modelValue',
],
data() { data() {
return { return {
focused: false, focused: false,
@ -88,8 +100,8 @@ export default createComponent({
}, },
watch: { watch: {
value() { modelValue(val) {
this.updateValue(this.value); this.updateValue(val);
this.resetValidation(); this.resetValidation();
this.validateWithTrigger('onChange'); this.validateWithTrigger('onChange');
this.$nextTick(this.adjustSize); this.$nextTick(this.adjustSize);
@ -97,7 +109,7 @@ export default createComponent({
}, },
mounted() { mounted() {
this.updateValue(this.value, this.formatTrigger); this.updateValue(this.modelValue, this.formatTrigger);
this.$nextTick(this.adjustSize); this.$nextTick(this.adjustSize);
if (this.vanForm) { if (this.vanForm) {
@ -114,7 +126,7 @@ export default createComponent({
computed: { computed: {
showClear() { showClear() {
if (this.clearable && !this.readonly) { if (this.clearable && !this.readonly) {
const hasValue = isDef(this.value) && this.value !== ''; const hasValue = isDef(this.modelValue) && this.modelValue !== '';
const trigger = const trigger =
this.clearTrigger === 'always' || this.clearTrigger === 'always' ||
(this.clearTrigger === 'focus' && this.focused); (this.clearTrigger === 'focus' && this.focused);
@ -132,30 +144,18 @@ export default createComponent({
} }
}, },
listeners() {
return {
...this.$listeners,
blur: this.onBlur,
focus: this.onFocus,
input: this.onInput,
click: this.onClickInput,
keypress: this.onKeypress,
};
},
labelStyle() { labelStyle() {
const labelWidth = this.getProp('labelWidth'); const labelWidth = this.getProp('labelWidth');
if (labelWidth) { if (labelWidth) {
return { width: addUnit(labelWidth) }; return { width: addUnit(labelWidth) };
} }
}, },
formValue() { formValue() {
if (this.children && (this.$scopedSlots.input || this.$slots.input)) { if (this.children && this.$slots.input) {
return this.children.value; return this.children.modelValue || this.children.value;
} }
return this.value; return this.modelValue;
}, },
}, },
@ -311,8 +311,8 @@ export default createComponent({
input.value = value; input.value = value;
} }
if (value !== this.value) { if (value !== this.modelValue) {
this.$emit('input', value); this.$emit('update:modelValue', value);
} }
this.currentValue = value; this.currentValue = value;
@ -340,7 +340,7 @@ export default createComponent({
onBlur(event) { onBlur(event) {
this.focused = false; this.focused = false;
this.updateValue(this.value, 'onBlur'); this.updateValue(this.modelValue, 'onBlur');
this.$emit('blur', event); this.$emit('blur', event);
this.validateWithTrigger('onBlur'); this.validateWithTrigger('onBlur');
resetScroll(); resetScroll();
@ -364,7 +364,7 @@ export default createComponent({
onClear(event) { onClear(event) {
preventDefault(event); preventDefault(event);
this.$emit('input', ''); this.$emit('update:modelValue', '');
this.$emit('clear', event); this.$emit('clear', event);
}, },
@ -412,41 +412,41 @@ export default createComponent({
genInput() { genInput() {
const { type } = this; const { type } = this;
const inputSlot = this.slots('input');
const inputAlign = this.getProp('inputAlign'); const inputAlign = this.getProp('inputAlign');
if (inputSlot) { if (this.$slots.input) {
return ( return (
<div <div
class={bem('control', [inputAlign, 'custom'])} class={bem('control', [inputAlign, 'custom'])}
onClick={this.onClickInput} onClick={this.onClickInput}
> >
{inputSlot} {this.$slots.input()}
</div> </div>
); );
} }
const inputProps = { const inputProps = {
...this.$attrs,
ref: 'input', ref: 'input',
name: this.name,
class: bem('control', inputAlign), class: bem('control', inputAlign),
domProps: { value: this.modelValue,
value: this.value, disabled: this.disabled,
}, readonly: this.readonly,
attrs: { placeholder: this.placeholder,
...this.$attrs, onBlur: this.onBlur,
name: this.name, onFocus: this.onFocus,
disabled: this.disabled, onInput: this.onInput,
readonly: this.readonly, onClick: this.onClickInput,
placeholder: this.placeholder, onKeypress: this.onKeypress,
}, // TODO
on: this.listeners,
// add model directive to skip IME composition // add model directive to skip IME composition
directives: [ // directives: [
{ // {
name: 'model', // name: 'model',
value: this.value, // value: this.modelValue,
}, // },
], // ],
}; };
if (type === 'textarea') { if (type === 'textarea') {
@ -472,12 +472,14 @@ export default createComponent({
}, },
genLeftIcon() { genLeftIcon() {
const showLeftIcon = this.slots('left-icon') || this.leftIcon; const leftIconSlot = this.$slots['left-icon'];
if (showLeftIcon) { if (this.leftIcon || leftIconSlot) {
return ( return (
<div class={bem('left-icon')} onClick={this.onClickLeftIcon}> <div class={bem('left-icon')} onClick={this.onClickLeftIcon}>
{this.slots('left-icon') || ( {leftIconSlot ? (
leftIconSlot()
) : (
<Icon name={this.leftIcon} classPrefix={this.iconPrefix} /> <Icon name={this.leftIcon} classPrefix={this.iconPrefix} />
)} )}
</div> </div>
@ -486,13 +488,14 @@ export default createComponent({
}, },
genRightIcon() { genRightIcon() {
const { slots } = this; const rightIconSlot = this.$slots['right-icon'];
const showRightIcon = slots('right-icon') || this.rightIcon;
if (showRightIcon) { if (this.rightIcon || rightIconSlot) {
return ( return (
<div class={bem('right-icon')} onClick={this.onClickRightIcon}> <div class={bem('right-icon')} onClick={this.onClickRightIcon}>
{slots('right-icon') || ( {rightIconSlot ? (
rightIconSlot()
) : (
<Icon name={this.rightIcon} classPrefix={this.iconPrefix} /> <Icon name={this.rightIcon} classPrefix={this.iconPrefix} />
)} )}
</div> </div>
@ -502,7 +505,7 @@ export default createComponent({
genWordLimit() { genWordLimit() {
if (this.showWordLimit && this.maxlength) { if (this.showWordLimit && this.maxlength) {
const count = (this.value || '').length; const count = (this.modelValue || '').length;
return ( return (
<div class={bem('word-limit')}> <div class={bem('word-limit')}>
@ -541,8 +544,8 @@ export default createComponent({
genLabel() { genLabel() {
const colon = this.getProp('colon') ? ':' : ''; const colon = this.getProp('colon') ? ':' : '';
if (this.slots('label')) { if (this.$slots.label) {
return [this.slots('label'), colon]; return [this.$slots.label(), colon];
} }
if (this.label) { if (this.label) {
@ -552,27 +555,25 @@ export default createComponent({
}, },
render() { render() {
const { slots } = this; const slots = this.$slots;
const labelAlign = this.getProp('labelAlign'); const labelAlign = this.getProp('labelAlign');
const scopedSlots = {
icon: this.genLeftIcon,
};
const Label = this.genLabel();
if (Label) {
scopedSlots.title = () => Label;
}
const extra = this.slots('extra');
if (extra) {
scopedSlots.extra = () => extra;
}
return ( return (
<Cell <Cell
icon={this.leftIcon} icon={this.leftIcon}
size={this.size} size={this.size}
class={bem({
error: this.showError,
disabled: this.disabled,
[`label-${labelAlign}`]: labelAlign,
'min-height': this.type === 'textarea' && !this.autosize,
})}
// TODO
// vSlot={{
// icon: this.genLeftIcon,
// title: this.genLabel,
// extra: slots.extra,
// }}
center={this.center} center={this.center}
border={this.border} border={this.border}
isLink={this.isLink} isLink={this.isLink}
@ -581,14 +582,7 @@ export default createComponent({
titleStyle={this.labelStyle} titleStyle={this.labelStyle}
valueClass={bem('value')} valueClass={bem('value')}
titleClass={[bem('label', labelAlign), this.labelClass]} titleClass={[bem('label', labelAlign), this.labelClass]}
scopedSlots={scopedSlots}
arrowDirection={this.arrowDirection} arrowDirection={this.arrowDirection}
class={bem({
error: this.showError,
disabled: this.disabled,
[`label-${labelAlign}`]: labelAlign,
'min-height': this.type === 'textarea' && !this.autosize,
})}
onClick={this.onClick} onClick={this.onClick}
> >
<div class={bem('body')}> <div class={bem('body')}>
@ -601,9 +595,7 @@ export default createComponent({
/> />
)} )}
{this.genRightIcon()} {this.genRightIcon()}
{slots('button') && ( {slots.button && <div class={bem('button')}>{slots.button()}</div>}
<div class={bem('button')}>{slots('button')}</div>
)}
</div> </div>
{this.genWordLimit()} {this.genWordLimit()}
{this.genMessage()} {this.genMessage()}

View File

@ -127,10 +127,10 @@ module.exports = {
// path: 'datetime-picker', // path: 'datetime-picker',
// title: 'DatetimePicker 时间选择', // title: 'DatetimePicker 时间选择',
// }, // },
// { {
// path: 'field', path: 'field',
// title: 'Field 输入框', title: 'Field 输入框',
// }, },
// { // {
// path: 'form', // path: 'form',
// title: 'Form 表单', // title: 'Form 表单',
@ -461,10 +461,10 @@ module.exports = {
// path: 'datetime-picker', // path: 'datetime-picker',
// title: 'DatetimePicker', // title: 'DatetimePicker',
// }, // },
// { {
// path: 'field', path: 'field',
// title: 'Field', title: 'Field',
// }, },
// { // {
// path: 'form', // path: 'form',
// title: 'Form', // title: 'Form',