feature: implament some event handlers and rename component to button-edit
This commit is contained in:
parent
8298f7e64f
commit
b7ef12bb60
|
@ -1,39 +1,59 @@
|
|||
import { defineComponent, computed } from 'vue';
|
||||
import { defineComponent, computed, toRefs } from 'vue';
|
||||
import type { SetupContext } from 'vue';
|
||||
import { InputGroupProps, inputGroupProps } from './input-group.props';
|
||||
import { useAppendButton } from './composition/use-append-button';
|
||||
import { buttonEditProps, ButtonEditProps } from './button-edit.props';
|
||||
import { useButton } from './composition/use-button';
|
||||
import { useClear } from './composition/use-clear';
|
||||
import { useTextBox } from './composition/use-text-box';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'FInputGroup',
|
||||
props: inputGroupProps,
|
||||
setup(props: InputGroupProps, context: SetupContext) {
|
||||
const inputGroupClass = computed(() => ({
|
||||
'input-group': true,
|
||||
'f-state-disable': props.disable,
|
||||
'f-state-editable': props.editable && !props.disable && !props.readonly,
|
||||
'f-state-readonly': props.readonly && !props.disable,
|
||||
}));
|
||||
name: 'FButtonEdit',
|
||||
props: buttonEditProps,
|
||||
emits: [
|
||||
'updateExtendInfo',
|
||||
'clear',
|
||||
'change',
|
||||
'clickHandle',
|
||||
'blurHandle',
|
||||
'focusHandle',
|
||||
'enterHandle',
|
||||
'iconMouseEnter',
|
||||
'iconMouseLeave',
|
||||
'keyupHandle',
|
||||
'keydownHandle',
|
||||
'inputClick',
|
||||
'input',
|
||||
'update:modelValue',
|
||||
],
|
||||
setup(props: ButtonEditProps, context: SetupContext) {
|
||||
const { modelValue } = toRefs(props);
|
||||
|
||||
const { inputGroupAppendClass, onClickAppendButton, onMouseEnterIcon, onMouseLeaveIcon } = useAppendButton(props, context);
|
||||
const { buttonClass, onClickButton, onMouseEnterButton, onMouseLeaveButton } = useButton(props, context);
|
||||
|
||||
const { showClearButton, onClearValue } = useClear(props, context);
|
||||
const { showClearButton, onClearValue, onMouseEnterTextBox, onMouseLeaveTextBox } = useClear(props, context);
|
||||
|
||||
const {
|
||||
hasFocusedTextBox,
|
||||
isTextBoxReadonly,
|
||||
textBoxClass,
|
||||
textBoxPlaceholder,
|
||||
textBoxTitle,
|
||||
onBlurTextBox,
|
||||
onClickTextBox,
|
||||
onEnterTextBox,
|
||||
onFocusTextBox,
|
||||
onInput,
|
||||
onMouseDownTextBox,
|
||||
onMouseOverTextBox,
|
||||
onTextBoxValueChange,
|
||||
} = useTextBox(props, context);
|
||||
|
||||
const inputGroupClass = computed(() => ({
|
||||
'input-group': true,
|
||||
'f-state-disable': props.disable,
|
||||
'f-state-editable': props.editable && !props.disable && !props.readonly,
|
||||
'f-state-readonly': props.readonly && !props.disable,
|
||||
'f-state-focus': hasFocusedTextBox,
|
||||
}));
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<div class="f-cmp-inputgroup" id={props.id}>
|
||||
|
@ -50,19 +70,21 @@ export default defineComponent({
|
|||
tabindex={props.tabIndex}
|
||||
title={textBoxTitle.value}
|
||||
type={props.inputType}
|
||||
value={modelValue.value}
|
||||
onBlur={onBlurTextBox}
|
||||
onClick={onClickTextBox}
|
||||
onFocus={onFocusTextBox}
|
||||
onKeydown={onEnterTextBox}
|
||||
onInput={onInput}
|
||||
onKeydown={onMouseEnterTextBox}
|
||||
onMousedown={onMouseDownTextBox}
|
||||
/>
|
||||
<div class={inputGroupAppendClass.value}>
|
||||
<div class={buttonClass.value}>
|
||||
{showClearButton.value && (
|
||||
<span class="input-group-text input-group-clear">
|
||||
<i class="f-icon modal_close"></i>
|
||||
</span>
|
||||
)}
|
||||
{props.appendButtonContent && <span class="input-group-text" v-html={props.appendButtonContent}></span>}
|
||||
{props.buttonContent && <span class="input-group-text" v-html={props.buttonContent}></span>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -2,7 +2,7 @@ import { ExtractPropTypes, PropType } from 'vue';
|
|||
|
||||
type TextAlignment = 'left' | 'center' | 'right';
|
||||
|
||||
export const inputGroupProps = {
|
||||
export const buttonEditProps = {
|
||||
/**
|
||||
* 组件标识
|
||||
*/
|
||||
|
@ -10,7 +10,7 @@ export const inputGroupProps = {
|
|||
/**
|
||||
* 扩展按钮显示内容,这是一段现在扩展按钮中的html标签
|
||||
*/
|
||||
appendButtonContent: { type: String, default: '<i class="f-icon f-icon-lookup"></i>' },
|
||||
buttonContent: { type: String, default: '<i class="f-icon f-icon-lookup"></i>' },
|
||||
/**
|
||||
* 启用输入框自动完成功能
|
||||
*/
|
||||
|
@ -31,6 +31,10 @@ export const inputGroupProps = {
|
|||
* 显示清空文本按钮
|
||||
*/
|
||||
enableClear: { type: Boolean, default: false },
|
||||
/**
|
||||
* 组件值
|
||||
*/
|
||||
modelValue:{type:String,default:''},
|
||||
/**
|
||||
* 将组件设置为只读,既不允许在输入框中录入,也不允许点击扩展按钮,但是允许复制输入框中的内容。
|
||||
*/
|
||||
|
@ -60,7 +64,6 @@ export const inputGroupProps = {
|
|||
* 输入框提示文本
|
||||
*/
|
||||
placeholder: { type: String, default: '' },
|
||||
|
||||
/**
|
||||
* 输入框最小长度
|
||||
*/
|
||||
|
@ -75,4 +78,4 @@ export const inputGroupProps = {
|
|||
tabIndex: Number,
|
||||
};
|
||||
|
||||
export type InputGroupProps = ExtractPropTypes<typeof inputGroupProps>;
|
||||
export type ButtonEditProps = ExtractPropTypes<typeof buttonEditProps>;
|
|
@ -0,0 +1,89 @@
|
|||
import { ComputedRef } from 'vue';
|
||||
|
||||
export interface UseButton {
|
||||
/**
|
||||
* 附加按钮的Class
|
||||
*/
|
||||
buttonClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
/**
|
||||
* 点击附加按钮事件响应函数
|
||||
*/
|
||||
onClickButton: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标移入附加按钮事件响应函数
|
||||
*/
|
||||
onMouseEnterButton: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 鼠标移出附加按钮事件响应函数
|
||||
*/
|
||||
onMouseLeaveButton: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 鼠标滑过附加按钮事件响应函数
|
||||
*/
|
||||
onMouseOverButton: () => void;
|
||||
}
|
||||
|
||||
export interface UseClear {
|
||||
/**
|
||||
* 显示清空按钮
|
||||
*/
|
||||
showClearButton: ComputedRef<boolean>;
|
||||
/**
|
||||
* 清空输入框值事件响应函数
|
||||
*/
|
||||
onClearValue: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标进入输入框事件响应函数
|
||||
*/
|
||||
onMouseEnterTextBox: ($event: KeyboardEvent) => void;
|
||||
|
||||
onMouseLeaveTextBox: ($event: Event) => void;
|
||||
}
|
||||
|
||||
export interface UseTextBox {
|
||||
hasFocusedTextBox: ComputedRef<boolean>;
|
||||
/**
|
||||
* 输入框是否处于只读状态
|
||||
*/
|
||||
isTextBoxReadonly: ComputedRef<boolean>;
|
||||
/**
|
||||
* 输入框Class
|
||||
*/
|
||||
textBoxClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
/**
|
||||
* 输入框提示语
|
||||
*/
|
||||
textBoxPlaceholder: ComputedRef<string>;
|
||||
/**
|
||||
* 输入框提示标签
|
||||
*/
|
||||
textBoxTitle: ComputedRef<string>;
|
||||
/**
|
||||
* 输入框失去焦点事件响应函数
|
||||
*/
|
||||
onBlurTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标点击输入框事件响应函数
|
||||
*/
|
||||
onClickTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框获得焦点事件响应函数
|
||||
*/
|
||||
onFocusTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框值变化事件
|
||||
*/
|
||||
onInput: ($event: Event) => void;
|
||||
/**
|
||||
* 鼠标点击输入框事件响应函数
|
||||
*/
|
||||
onMouseDownTextBox: ($event: MouseEvent) => void;
|
||||
/**
|
||||
* 鼠标滑过输入框事件响应函数
|
||||
*/
|
||||
onMouseOverTextBox: ($event: Event) => void;
|
||||
/**
|
||||
* 输入框值变化事件响应函数
|
||||
*/
|
||||
onTextBoxValueChange: (value: string, emit: boolean) => void;
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import { UseButton } from './types';
|
||||
import { computed, SetupContext } from 'vue';
|
||||
import { ButtonEditProps } from '../button-edit.props';
|
||||
|
||||
export function useButton(props: ButtonEditProps, context: SetupContext): UseButton {
|
||||
const buttonClass = computed(() => ({
|
||||
'input-group-append': true,
|
||||
'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
|
||||
}));
|
||||
|
||||
const canClickAppendButton = computed(() => props.showButtonWhenDisabled || ((!props.editable || !props.readonly) && !props.disable));
|
||||
|
||||
function onClickButton($event: Event) {
|
||||
if (canClickAppendButton.value) {
|
||||
context.emit('clickButton', { origin: $event, value: this.value });
|
||||
}
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
function onMouseEnterButton($event: MouseEvent) {
|
||||
context.emit('mouseEnter', $event);
|
||||
}
|
||||
function onMouseLeaveButton($event: MouseEvent) {
|
||||
context.emit('mouseLeaveIcon', $event);
|
||||
}
|
||||
|
||||
function onMouseOverButton() {
|
||||
context.emit('mouseOverButton');
|
||||
}
|
||||
|
||||
return {
|
||||
buttonClass,
|
||||
onClickButton,
|
||||
onMouseEnterButton,
|
||||
onMouseLeaveButton,
|
||||
onMouseOverButton,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
import { computed, ref, SetupContext } from 'vue';
|
||||
import { ButtonEditProps } from '../button-edit.props';
|
||||
import { UseClear } from './types';
|
||||
import { useTextBox } from './use-text-box';
|
||||
|
||||
export function useClear(props: ButtonEditProps, context: SetupContext): UseClear {
|
||||
const hasShownClearButton = ref(false);
|
||||
const showClearButton = computed(() => props.enableClear && !props.readonly && !props.disable);
|
||||
|
||||
const { onTextBoxValueChange } = useTextBox(props, context);
|
||||
|
||||
function toggleClearIcon($event: any, isShow = false) {
|
||||
const display = isShow ? '' : 'none';
|
||||
const clearIcon = $event.target.querySelector('.input-group-clear');
|
||||
if (clearIcon) {
|
||||
clearIcon.style.display = display;
|
||||
}
|
||||
}
|
||||
|
||||
function onClearValue($event: Event) {
|
||||
const flag1 = !props.readonly && !props.disable && props.editable;
|
||||
const flag2 = !props.editable;
|
||||
$event.stopPropagation();
|
||||
if (flag1 || flag2) {
|
||||
onTextBoxValueChange('', false);
|
||||
hasShownClearButton.value = false;
|
||||
context.emit('clear');
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseEnterTextBox($event: Event) {
|
||||
if (this.value) {
|
||||
if (!props.editable) {
|
||||
if (!props.disable) {
|
||||
hasShownClearButton.value = true;
|
||||
}
|
||||
} else if (!props.readonly && !props.disable) {
|
||||
hasShownClearButton.value = true;
|
||||
}
|
||||
}
|
||||
if (hasShownClearButton.value) {
|
||||
this.toggleClearIcon($event, true);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseLeaveTextBox($event: Event) {
|
||||
hasShownClearButton.value = false;
|
||||
toggleClearIcon($event, false);
|
||||
}
|
||||
|
||||
return {
|
||||
showClearButton,
|
||||
onClearValue,
|
||||
onMouseEnterTextBox,
|
||||
onMouseLeaveTextBox,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
import { isContext } from 'vm';
|
||||
import { computed, ref, SetupContext, watch } from 'vue';
|
||||
import { ButtonEditProps } from '../button-edit.props';
|
||||
import { UseTextBox } from './types';
|
||||
|
||||
export function useTextBox(props: ButtonEditProps, context: SetupContext): UseTextBox {
|
||||
const textBoxTitle = computed(() => (props.enableTitle ? props.modelValue : ''));
|
||||
|
||||
const textBoxPlaceholder = computed(() => ((props.disable || props.readonly) && !props.forcePlaceholder ? '' : props.placeholder));
|
||||
|
||||
const isTextBoxReadonly = computed(() => props.readonly || !props.editable);
|
||||
|
||||
let focusState = false;
|
||||
|
||||
const hasFocusedTextBox = computed(() => focusState);
|
||||
|
||||
const textBoxClass = computed(() => ({
|
||||
'text-left': props.textAlign === 'left',
|
||||
'text-center': props.textAlign === 'center',
|
||||
'text-right': props.textAlign === 'right',
|
||||
'form-control': true,
|
||||
'f-utils-fill': true,
|
||||
}));
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(value: string) => context.emit('change', value)
|
||||
);
|
||||
|
||||
function onBlurTextBox($event: Event) {
|
||||
focusState = false;
|
||||
context.emit('blur', $event);
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
function onClickTextBox($event: Event) {
|
||||
context.emit('click', $event);
|
||||
}
|
||||
|
||||
function onFocusTextBox($event: Event) {
|
||||
if (props.disable) {
|
||||
return;
|
||||
}
|
||||
focusState = true;
|
||||
if (!isTextBoxReadonly.value) {
|
||||
context.emit('focus', $event);
|
||||
}
|
||||
}
|
||||
|
||||
function onInput($event: Event) {
|
||||
context.emit('input', ($event.target as HTMLInputElement).value);
|
||||
context.emit('update:modelValue', ($event.target as HTMLInputElement).value);
|
||||
}
|
||||
|
||||
function onMouseDownTextBox($event: MouseEvent) {
|
||||
const target = $event.target as HTMLElement;
|
||||
if (target.tagName !== 'INPUT') {
|
||||
$event.preventDefault();
|
||||
}
|
||||
$event.stopPropagation();
|
||||
}
|
||||
|
||||
function onMouseOverTextBox($event: Event) {
|
||||
console.log('on onMouseOverInExtentInfo');
|
||||
}
|
||||
|
||||
function onTextBoxValueChange(newValue: string, emit = true) {
|
||||
if (props.modelValue !== newValue) {
|
||||
props.modelValue = newValue;
|
||||
if (emit) {
|
||||
context.emit('change', newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
hasFocusedTextBox,
|
||||
isTextBoxReadonly,
|
||||
textBoxClass,
|
||||
textBoxPlaceholder,
|
||||
textBoxTitle,
|
||||
onBlurTextBox,
|
||||
onClickTextBox,
|
||||
onFocusTextBox,
|
||||
onInput,
|
||||
onMouseDownTextBox,
|
||||
onMouseOverTextBox,
|
||||
onTextBoxValueChange,
|
||||
};
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
import { ComputedRef } from 'vue';
|
||||
|
||||
export interface UseAppendButton {
|
||||
inputGroupAppendClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
onClickAppendButton: ($event: Event) => void;
|
||||
onMouseEnterIcon: ($event: MouseEvent) => void;
|
||||
onMouseLeaveIcon: ($event: MouseEvent) => void;
|
||||
}
|
||||
|
||||
export interface UseClear {
|
||||
showClearButton: ComputedRef<boolean>;
|
||||
onClearValue: ($event: Event) => void;
|
||||
}
|
||||
|
||||
export interface UseTextBox {
|
||||
isTextBoxReadonly: ComputedRef<boolean>;
|
||||
textBoxClass: ComputedRef<Record<string, boolean | undefined>>;
|
||||
textBoxPlaceholder: ComputedRef<string>;
|
||||
textBoxTitle: ComputedRef<string>;
|
||||
onBlurTextBox: ($event: Event) => void;
|
||||
onClickTextBox: ($event: Event) => void;
|
||||
onEnterTextBox: ($event: KeyboardEvent) => void;
|
||||
onFocusTextBox: ($event: Event) => void;
|
||||
onMouseDownTextBox: ($event: MouseEvent) => void;
|
||||
onMouseOverTextBox: ($event: Event) => void;
|
||||
onTextBoxValueChange: (value: string, emit: boolean) => void;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
import { computed, SetupContext } from 'vue';
|
||||
import { InputGroupProps } from '../input-group.props';
|
||||
|
||||
export function useAppendButton(props: InputGroupProps, setupContext: SetupContext) {
|
||||
const inputGroupAppendClass = computed(() => ({
|
||||
'input-group-append': true,
|
||||
'append-force-show': props.showButtonWhenDisabled && (props.readonly || props.disable),
|
||||
}));
|
||||
|
||||
function onMouseEnterIcon(e: MouseEvent) {
|
||||
console.log('on onIconMouseEnter');
|
||||
}
|
||||
function onMouseLeaveIcon(e: MouseEvent) {
|
||||
console.log('on onIconMouseLeave');
|
||||
}
|
||||
|
||||
function onClickAppendButton(event: Event) {
|
||||
console.log('on onClickHandle');
|
||||
}
|
||||
|
||||
return {
|
||||
inputGroupAppendClass,
|
||||
onClickAppendButton,
|
||||
onMouseEnterIcon,
|
||||
onMouseLeaveIcon
|
||||
};
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
import { computed, SetupContext } from 'vue';
|
||||
import { InputGroupProps } from '../input-group.props';
|
||||
import { UseClear } from './types';
|
||||
|
||||
export function useClear(props: InputGroupProps, setupContext: SetupContext): UseClear {
|
||||
const showClearButton = computed(() => props.enableClear && !props.readonly && !props.disable);
|
||||
|
||||
function onClearValue($event: Event) {
|
||||
console.log('on onClearValue');
|
||||
}
|
||||
|
||||
return {
|
||||
showClearButton,
|
||||
onClearValue
|
||||
};
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
import { computed, SetupContext } from 'vue';
|
||||
import { InputGroupProps } from '../input-group.props';
|
||||
import { UseTextBox } from './types';
|
||||
|
||||
export function useTextBox(props: InputGroupProps, setupContext: SetupContext): UseTextBox {
|
||||
const textBoxTitle = computed(() => (props.enableTitle ? '' : ''));
|
||||
|
||||
const textBoxPlaceholder = computed(() => ((props.disable || props.readonly) && !props.forcePlaceholder ? '' : props.placeholder));
|
||||
|
||||
const isTextBoxReadonly = computed(() => props.readonly || !props.editable);
|
||||
|
||||
const textBoxClass = computed(() => ({
|
||||
'text-left': props.textAlign === 'left',
|
||||
'text-center': props.textAlign === 'center',
|
||||
'text-right': props.textAlign === 'right',
|
||||
'form-control': true,
|
||||
'f-utils-fill': true,
|
||||
}));
|
||||
|
||||
function onBlurTextBox($event: Event) {
|
||||
console.log('on blur');
|
||||
}
|
||||
|
||||
function onClickTextBox($event: Event) {
|
||||
console.log('on onInputClick');
|
||||
}
|
||||
|
||||
function onEnterTextBox($event: KeyboardEvent) {
|
||||
console.log('on onEnter');
|
||||
}
|
||||
|
||||
function onFocusTextBox($event: Event) {
|
||||
console.log('on onInputFocus');
|
||||
}
|
||||
|
||||
function onMouseDownTextBox($event: MouseEvent) {
|
||||
console.log('on onMousedown');
|
||||
}
|
||||
|
||||
function onMouseOverTextBox($event: Event) {
|
||||
console.log('on onMouseOverInExtentInfo');
|
||||
}
|
||||
|
||||
function onTextBoxValueChange(val: string, emit = true) {
|
||||
console.log('on onValueChange');
|
||||
}
|
||||
|
||||
return {
|
||||
isTextBoxReadonly,
|
||||
textBoxClass,
|
||||
textBoxPlaceholder,
|
||||
textBoxTitle,
|
||||
onBlurTextBox,
|
||||
onClickTextBox,
|
||||
onEnterTextBox,
|
||||
onFocusTextBox,
|
||||
onMouseDownTextBox,
|
||||
onMouseOverTextBox,
|
||||
onTextBoxValueChange
|
||||
};
|
||||
}
|
|
@ -2,8 +2,8 @@
|
|||
// This starter template is using Vue 3 <script setup> SFCs
|
||||
// Check out https://vuejs.org/api/sfc-script-setup.html#script-setup
|
||||
import { ref } from "vue";
|
||||
import HelloWorld from './components/hello-world.vue'
|
||||
import InputGroup from "../components/input-group/src/input-group.component";
|
||||
import HelloWorld from './components/hello-world.vue';
|
||||
import ButtonEdit from "../components/button-edit/src/button-edit.component";
|
||||
|
||||
const canEdit = ref(true);
|
||||
const canAutoComplete = ref(false);
|
||||
|
@ -24,7 +24,7 @@ const canAutoComplete = ref(false);
|
|||
<input type="checkbox" id="checkbox" v-model="canAutoComplete" />
|
||||
<label for="checkbox">auto complete:{{ canAutoComplete }}</label>
|
||||
<HelloWorld msg="Vite + Vue" />
|
||||
<InputGroup :editable="canEdit" :auto-complete="canAutoComplete" :enable-clear="true"></InputGroup>
|
||||
<ButtonEdit :editable="canEdit" :auto-complete="canAutoComplete" :enable-clear="true"></ButtonEdit>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
|
Loading…
Reference in New Issue