Replace textControlMixin to vue composition style

This commit is contained in:
timongh 2023-02-08 14:25:16 +08:00
parent d49d7b8909
commit 241ae31d9c
3 changed files with 101 additions and 74 deletions

View File

@ -1,9 +1,9 @@
<template> <template>
<div class="be-text-area" role="text"> <div class="be-text-area" role="text">
<textarea <textarea
ref="input" ref="inputRef"
type="text" type="text"
v-bind="restattrs" v-bind="restAttrs"
:value="text" :value="text"
@change.stop="change" @change.stop="change"
@input.stop="input" @input.stop="input"
@ -14,11 +14,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
import { textControlMixin } from './text-control' import { textControlProps, useTextControl } from './text-control'
export default defineComponent({ export default defineComponent({
name: 'TextArea', name: 'TextArea',
mixins: [textControlMixin], props: textControlProps,
setup: useTextControl,
}) })
</script> </script>
<style lang="scss"> <style lang="scss">

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="be-textbox" role="textbox" :class="{ linear }"> <div class="be-textbox" role="textbox" :class="{ linear }">
<input <input
ref="input" ref="inputRef"
type="text" type="text"
v-bind="restAttrs" v-bind="restAttrs"
:value="text" :value="text"
@ -16,17 +16,19 @@
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue' import { defineComponent } from 'vue'
import { textControlMixin } from './text-control' import { textControlProps, useTextControl } from './text-control'
export default defineComponent({ export default defineComponent({
name: 'TextBox', name: 'TextBox',
mixins: [textControlMixin],
props: { props: {
linear: { linear: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
...textControlProps,
}, },
emits: ['update:text'],
setup: useTextControl,
}) })
</script> </script>

View File

@ -1,9 +1,7 @@
import { defineComponent } from 'vue' import type { SetupContext, Ref, PropType, ComputedRef } from 'vue'
import type { PropType } from 'vue' import { ref, computed } from 'vue'
export const textControlMixin = defineComponent({ export const textControlProps = {
inheritAttrs: false,
props: {
text: { text: {
type: String, type: String,
required: false, required: false,
@ -15,57 +13,83 @@ export const textControlMixin = defineComponent({
default: false, default: false,
}, },
validator: { validator: {
type: Function as PropType<(value: string, oldValue: string) => string>, type: Function as PropType<(value: string, oldValue: string) => string | undefined>,
default: undefined, default: undefined,
}, },
}
export const useTextControl = (
props: {
text: string
changeOnBlur: boolean
validator: (value: string, oldValue: string) => string | undefined
}, },
emits: ['update:text'], { emit }: SetupContext<{ 'update:text': (value: string) => boolean }>,
data() { ): {
return { inputRef: Ref<HTMLInputElement | null>
composing: false, composing: Ref<boolean>
restAttrs: lodash.omit( restAttrs: ComputedRef<Record<string, unknown>>
this.$attrs, emitChange: () => void
'onChange', input: () => void
'onInput', change: () => void
'onCompositionstart', compositionStart: () => void
'onCompositionend', compositionEnd: () => void
), focus: () => void
} } => {
}, const inputRef = ref(null) as Ref<HTMLInputElement | null>
methods: { const composing = ref(false) as Ref<boolean>
emitChange() { const restAttrs = computed(() =>
const input = (this.$refs as any).input as { value: any } lodash.omit(props, 'onChange', 'onInput', 'onCompositionstart', 'onCompositionend'),
let { value } = input )
if (this.validator) {
value = this.validator(value, this.text) const emitChange = () => {
if (this.changeOnBlur) { let { value } = inputRef.value
input.value = value if (props.validator) {
value = props.validator(value, props.text)
if (props.changeOnBlur) {
inputRef.value.value = value
} }
} }
if (value === this.text) { if (value === props.text) {
return return
} }
this.$emit('update:text', value) emit('update:text', value)
}, }
input() {
if (!this.changeOnBlur && !this.composing) { const input = () => {
this.emitChange() if (!props.changeOnBlur && !composing.value) {
emitChange()
}
}
const change = () => {
if (props.changeOnBlur && !composing.value) {
emitChange()
}
}
const compositionStart = () => {
composing.value = true
}
const compositionEnd = () => {
composing.value = false
input()
}
const focus = () => {
inputRef.value.focus()
}
return {
inputRef,
composing,
restAttrs,
emitChange,
input,
change,
compositionStart,
compositionEnd,
focus,
} }
},
change() {
if (this.changeOnBlur && !this.composing) {
this.emitChange()
} }
},
compositionStart() {
this.composing = true
},
compositionEnd() {
this.composing = false
this.input()
},
focus() {
;(this.$refs as any).input.focus()
},
},
})