refactor components/form/textarea.vue to composition API
This commit is contained in:
parent
670c229cd0
commit
9a236bd862
1 changed files with 69 additions and 131 deletions
|
@ -26,118 +26,70 @@
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts" setup>
|
||||||
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
|
import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
|
||||||
import { debounce } from 'throttle-debounce';
|
import { debounce } from 'throttle-debounce';
|
||||||
import MkButton from '@/components/ui/button.vue';
|
import MkButton from '@/components/ui/button.vue';
|
||||||
import { i18n } from '@/i18n';
|
import { i18n } from '@/i18n';
|
||||||
|
|
||||||
export default defineComponent({
|
const emit = defineEmits<{
|
||||||
components: {
|
(ev: 'change', v: any): void;
|
||||||
MkButton,
|
(ev: 'keydown', v: KeyboardEvent): void;
|
||||||
},
|
(ev: 'enter'): void;
|
||||||
|
(ev: 'update:modelValue', v: string): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
props: {
|
const props = withDefaults(defineProps<{
|
||||||
modelValue: {
|
modelValue: string;
|
||||||
required: true,
|
type?: string;
|
||||||
},
|
required?: boolean;
|
||||||
type: {
|
readonly?: boolean;
|
||||||
type: String,
|
disabled?: boolean;
|
||||||
required: false,
|
pattern?: string;
|
||||||
},
|
placeholder?: string;
|
||||||
required: {
|
autofocus?: boolean;
|
||||||
type: Boolean,
|
autocomplete?: boolean;
|
||||||
required: false,
|
spellcheck?: boolean;
|
||||||
},
|
code?: boolean;
|
||||||
readonly: {
|
tall?: boolean;
|
||||||
type: Boolean,
|
pre?: boolean;
|
||||||
required: false,
|
debounce?: boolean;
|
||||||
},
|
manualSave?: boolean;
|
||||||
disabled: {
|
}>(), {
|
||||||
type: Boolean,
|
autofocus: false,
|
||||||
required: false,
|
tall: false,
|
||||||
},
|
pre: false,
|
||||||
pattern: {
|
manualSave: false,
|
||||||
type: String,
|
});
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
placeholder: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
autofocus: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
autocomplete: {
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
spellcheck: {
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
code: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
},
|
|
||||||
tall: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
pre: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
debounce: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
manualSave: {
|
|
||||||
type: Boolean,
|
|
||||||
required: false,
|
|
||||||
default: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
emits: ['change', 'keydown', 'enter', 'update:modelValue'],
|
const { modelValue, autofocus } = toRefs(props);
|
||||||
|
// modelValue is read only, so a separate ref is needed.
|
||||||
|
const v = $ref(modelValue.value);
|
||||||
|
|
||||||
setup(props, context) {
|
const focused = $ref(false);
|
||||||
const { modelValue, autofocus } = toRefs(props);
|
const changed = $ref(false);
|
||||||
const v = ref(modelValue.value);
|
const invalid = $ref(false);
|
||||||
const focused = ref(false);
|
const filled = computed(() => modelValue.value !== '' && modelValue.value != null);
|
||||||
const changed = ref(false);
|
const inputEl = $ref(null);
|
||||||
const invalid = ref(false);
|
|
||||||
const filled = computed(() => v.value !== '' && v.value != null);
|
|
||||||
const inputEl = ref(null);
|
|
||||||
|
|
||||||
const focus = () => inputEl.value.focus();
|
const focus = () => inputEl.focus();
|
||||||
const onInput = (ev) => {
|
const onInput = evt => {
|
||||||
changed.value = true;
|
changed = true;
|
||||||
context.emit('change', ev);
|
emit('change', evt);
|
||||||
};
|
};
|
||||||
const onKeydown = (ev: KeyboardEvent) => {
|
const onKeydown = (evt: KeyboardEvent) => {
|
||||||
context.emit('keydown', ev);
|
emit('keydown', evt);
|
||||||
|
if (evt.code === 'Enter') {
|
||||||
if (ev.code === 'Enter') {
|
emit('enter');
|
||||||
context.emit('enter');
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const updated = () => {
|
||||||
|
changed = false;
|
||||||
|
emit('update:modelValue', v);
|
||||||
|
};
|
||||||
|
const debouncedUpdated = debounce(1000, updated);
|
||||||
|
|
||||||
const updated = () => {
|
watch(modelValue, newValue => {
|
||||||
changed.value = false;
|
|
||||||
context.emit('update:modelValue', v.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const debouncedUpdated = debounce(1000, updated);
|
|
||||||
|
|
||||||
watch(modelValue, newValue => {
|
|
||||||
v.value = newValue;
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(v, newValue => {
|
|
||||||
if (!props.manualSave) {
|
if (!props.manualSave) {
|
||||||
if (props.debounce) {
|
if (props.debounce) {
|
||||||
debouncedUpdated();
|
debouncedUpdated();
|
||||||
|
@ -146,30 +98,16 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invalid.value = inputEl.value.validity.badInput;
|
invalid = inputEl.validity.badInput;
|
||||||
});
|
});
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
|
onMounted(() => {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
if (autofocus.value) {
|
if (props.autofocus) {
|
||||||
focus();
|
inputEl.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
v,
|
|
||||||
focused,
|
|
||||||
invalid,
|
|
||||||
changed,
|
|
||||||
filled,
|
|
||||||
inputEl,
|
|
||||||
focus,
|
|
||||||
onInput,
|
|
||||||
onKeydown,
|
|
||||||
updated,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue