mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-06 03:57:59 +08:00
refactor(NumberKeyboard): refactor with composition api
This commit is contained in:
parent
ad5980c914
commit
14c1d4ea77
@ -1,20 +1,12 @@
|
|||||||
import { Teleport, Transition } from 'vue';
|
import { ref, watch, computed, Teleport, Transition } from 'vue';
|
||||||
import { createNamespace } from '../utils';
|
import { createNamespace } from '../utils';
|
||||||
import { stopPropagation } from '../utils/dom/event';
|
import { stopPropagation } from '../utils/dom/event';
|
||||||
import { BindEventMixin } from '../mixins/bind-event';
|
import { useClickOutside } from '../composition/use-click-outside';
|
||||||
import Key from './Key';
|
import Key from './Key';
|
||||||
|
|
||||||
const [createComponent, bem] = createNamespace('number-keyboard');
|
const [createComponent, bem] = createNamespace('number-keyboard');
|
||||||
|
|
||||||
export default createComponent({
|
export default createComponent({
|
||||||
mixins: [
|
|
||||||
BindEventMixin(function (bind) {
|
|
||||||
if (this.hideOnClickOutside) {
|
|
||||||
bind(document.body, 'touchstart', this.onBlur);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
show: Boolean,
|
show: Boolean,
|
||||||
title: String,
|
title: String,
|
||||||
@ -67,47 +59,30 @@ export default createComponent({
|
|||||||
'update:modelValue',
|
'update:modelValue',
|
||||||
],
|
],
|
||||||
|
|
||||||
watch: {
|
setup(props, { emit, slots }) {
|
||||||
show(val) {
|
const rootRef = ref();
|
||||||
if (!this.transition) {
|
|
||||||
this.$emit(val ? 'show' : 'hide');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
const genBasicKeys = () => {
|
||||||
keys() {
|
|
||||||
if (this.theme === 'custom') {
|
|
||||||
return this.genCustomKeys();
|
|
||||||
}
|
|
||||||
return this.genDefaultKeys();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
genBasicKeys() {
|
|
||||||
const keys = [];
|
const keys = [];
|
||||||
for (let i = 1; i <= 9; i++) {
|
for (let i = 1; i <= 9; i++) {
|
||||||
keys.push({ text: i });
|
keys.push({ text: i });
|
||||||
}
|
}
|
||||||
return keys;
|
return keys;
|
||||||
},
|
};
|
||||||
|
|
||||||
genDefaultKeys() {
|
const genDefaultKeys = () => [
|
||||||
return [
|
...genBasicKeys(),
|
||||||
...this.genBasicKeys(),
|
{ text: props.extraKey, type: 'extra' },
|
||||||
{ text: this.extraKey, type: 'extra' },
|
{ text: 0 },
|
||||||
{ text: 0 },
|
{
|
||||||
{
|
text: props.showDeleteKey ? props.deleteButtonText : '',
|
||||||
text: this.showDeleteKey ? this.deleteButtonText : '',
|
type: props.showDeleteKey ? 'delete' : '',
|
||||||
type: this.showDeleteKey ? 'delete' : '',
|
},
|
||||||
},
|
];
|
||||||
];
|
|
||||||
},
|
|
||||||
|
|
||||||
genCustomKeys() {
|
const genCustomKeys = () => {
|
||||||
const keys = this.genBasicKeys();
|
const keys = genBasicKeys();
|
||||||
const { extraKey } = this;
|
const { extraKey } = props;
|
||||||
const extraKeys = Array.isArray(extraKey) ? extraKey : [extraKey];
|
const extraKeys = Array.isArray(extraKey) ? extraKey : [extraKey];
|
||||||
|
|
||||||
if (extraKeys.length === 1) {
|
if (extraKeys.length === 1) {
|
||||||
@ -124,47 +99,53 @@ export default createComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return keys;
|
return keys;
|
||||||
},
|
};
|
||||||
|
|
||||||
onBlur() {
|
const keys = computed(() =>
|
||||||
this.show && this.$emit('blur');
|
props.theme === 'custom' ? genCustomKeys() : genDefaultKeys()
|
||||||
},
|
);
|
||||||
|
|
||||||
onClose() {
|
const onBlur = () => {
|
||||||
this.$emit('close');
|
if (props.show) {
|
||||||
this.onBlur();
|
emit('blur');
|
||||||
},
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onAnimationEnd() {
|
const onClose = () => {
|
||||||
this.$emit(this.show ? 'show' : 'hide');
|
emit('close');
|
||||||
},
|
onBlur();
|
||||||
|
};
|
||||||
|
|
||||||
onPress(text, type) {
|
const onAnimationEnd = () => {
|
||||||
|
emit(props.show ? 'show' : 'hide');
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPress = (text, type) => {
|
||||||
if (text === '') {
|
if (text === '') {
|
||||||
if (type === 'extra') {
|
if (type === 'extra') {
|
||||||
this.onBlur();
|
onBlur();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const value = this.modelValue;
|
const value = props.modelValue;
|
||||||
|
|
||||||
if (type === 'delete') {
|
if (type === 'delete') {
|
||||||
this.$emit('delete');
|
emit('delete');
|
||||||
this.$emit('update:modelValue', value.slice(0, value.length - 1));
|
emit('update:modelValue', value.slice(0, value.length - 1));
|
||||||
} else if (type === 'close') {
|
} else if (type === 'close') {
|
||||||
this.onClose();
|
onClose();
|
||||||
} else if (value.length < this.maxlength) {
|
} else if (value.length < props.maxlength) {
|
||||||
this.$emit('input', text);
|
emit('input', text);
|
||||||
this.$emit('update:modelValue', value + text);
|
emit('update:modelValue', value + text);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
|
|
||||||
genTitle() {
|
const renderTitle = () => {
|
||||||
const { title, theme, closeButtonText } = this;
|
const { title, theme, closeButtonText } = props;
|
||||||
const titleLeft = this.$slots['title-left'];
|
const leftSlot = slots['title-left'];
|
||||||
const showClose = closeButtonText && theme === 'default';
|
const showClose = closeButtonText && theme === 'default';
|
||||||
const showTitle = title || showClose || titleLeft;
|
const showTitle = title || showClose || leftSlot;
|
||||||
|
|
||||||
if (!showTitle) {
|
if (!showTitle) {
|
||||||
return;
|
return;
|
||||||
@ -172,26 +153,26 @@ export default createComponent({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={bem('header')}>
|
<div class={bem('header')}>
|
||||||
{titleLeft && <span class={bem('title-left')}>{titleLeft}</span>}
|
{leftSlot && <span class={bem('title-left')}>{leftSlot()}</span>}
|
||||||
{title && <h2 class={bem('title')}>{title}</h2>}
|
{title && <h2 class={bem('title')}>{title}</h2>}
|
||||||
{showClose && (
|
{showClose && (
|
||||||
<button type="button" class={bem('close')} onClick={this.onClose}>
|
<button type="button" class={bem('close')} onClick={onClose}>
|
||||||
{closeButtonText}
|
{closeButtonText}
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
};
|
||||||
|
|
||||||
genKeys() {
|
const renderKeys = () => {
|
||||||
return this.keys.map((key) => {
|
return keys.value.map((key) => {
|
||||||
const slots = {};
|
const slots = {};
|
||||||
|
|
||||||
if (key.type === 'delete') {
|
if (key.type === 'delete') {
|
||||||
slots.default = this.$slots.delete;
|
slots.default = slots.delete;
|
||||||
}
|
}
|
||||||
if (key.type === 'extra') {
|
if (key.type === 'extra') {
|
||||||
slots.default = this.$slots['extra-key'];
|
slots.default = slots['extra-key'];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -202,64 +183,83 @@ export default createComponent({
|
|||||||
type={key.type}
|
type={key.type}
|
||||||
wider={key.wider}
|
wider={key.wider}
|
||||||
color={key.color}
|
color={key.color}
|
||||||
onPress={this.onPress}
|
onPress={onPress}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
|
|
||||||
genSidebar() {
|
const renderSidebar = () => {
|
||||||
if (this.theme === 'custom') {
|
if (props.theme === 'custom') {
|
||||||
return (
|
return (
|
||||||
<div class={bem('sidebar')}>
|
<div class={bem('sidebar')}>
|
||||||
{this.showDeleteKey && (
|
{props.showDeleteKey && (
|
||||||
<Key
|
<Key
|
||||||
v-slots={{ delete: this.$slots.delete }}
|
v-slots={{ delete: slots.delete }}
|
||||||
large
|
large
|
||||||
text={this.deleteButtonText}
|
text={props.deleteButtonText}
|
||||||
type="delete"
|
type="delete"
|
||||||
onPress={this.onPress}
|
onPress={onPress}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Key
|
<Key
|
||||||
large
|
large
|
||||||
text={this.closeButtonText}
|
text={props.closeButtonText}
|
||||||
type="close"
|
type="close"
|
||||||
color="blue"
|
color="blue"
|
||||||
loading={this.closeButtonLoading}
|
loading={props.closeButtonLoading}
|
||||||
onPress={this.onPress}
|
onPress={onPress}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
};
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
watch(
|
||||||
const Title = this.genTitle();
|
() => props.show,
|
||||||
const Content = (
|
(value) => {
|
||||||
<Transition name={this.transition ? 'van-slide-up' : ''}>
|
if (!props.transition) {
|
||||||
<div
|
emit(value ? 'show' : 'hide');
|
||||||
vShow={this.show}
|
}
|
||||||
style={{ zIndex: this.zIndex }}
|
}
|
||||||
class={bem({ unfit: !this.safeAreaInsetBottom, 'with-title': Title })}
|
|
||||||
onTouchstart={stopPropagation}
|
|
||||||
onAnimationend={this.onAnimationEnd}
|
|
||||||
onWebkitAnimationEnd={this.onAnimationEnd}
|
|
||||||
>
|
|
||||||
{Title}
|
|
||||||
<div class={bem('body')}>
|
|
||||||
<div class={bem('keys')}>{this.genKeys()}</div>
|
|
||||||
{this.genSidebar()}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.teleport) {
|
useClickOutside({
|
||||||
return <Teleport to={this.teleport}>{Content}</Teleport>;
|
event: 'touchstart',
|
||||||
}
|
element: rootRef,
|
||||||
|
callback: onClose,
|
||||||
|
});
|
||||||
|
|
||||||
return Content;
|
return () => {
|
||||||
|
const Title = renderTitle();
|
||||||
|
const Content = (
|
||||||
|
<Transition name={props.transition ? 'van-slide-up' : ''}>
|
||||||
|
<div
|
||||||
|
ref={rootRef}
|
||||||
|
vShow={props.show}
|
||||||
|
style={{ zIndex: props.zIndex }}
|
||||||
|
class={bem({
|
||||||
|
unfit: !props.safeAreaInsetBottom,
|
||||||
|
'with-title': !!Title,
|
||||||
|
})}
|
||||||
|
onTouchstart={stopPropagation}
|
||||||
|
onAnimationend={onAnimationEnd}
|
||||||
|
onWebkitAnimationEnd={onAnimationEnd}
|
||||||
|
>
|
||||||
|
{Title}
|
||||||
|
<div class={bem('body')}>
|
||||||
|
<div class={bem('keys')}>{renderKeys()}</div>
|
||||||
|
{renderSidebar()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (props.teleport) {
|
||||||
|
return <Teleport to={props.teleport}>{Content}</Teleport>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Content;
|
||||||
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user