一、背景:

    使用select的dropdownRender,里面渲染表格,点击表格行,获取相关内容到下拉框中,测试发现有的电脑点击后下拉框消失,但是数据没选中,或者偶尔选中失灵。

 

二、贴下大致代码:

html

<Select
        :value="value"
        :dropdownStyle="{
            minWidth: '800px',
            padding: 0,
            border: 0,
        }"
        :options="tableData"
        :dropdownMatchSelectWidth="300"
        showSearch
        @focus="focus"
        @search="search"
    >
        <template #dropdownRender>
            <VxeGrid
                v-if="showTable"
                v-bind="gridOptions"
                ref="accountSearchDownTable"
                @current-change="selectData"
            >
                ...
            </VxeGrid>
        </template>
    </YdSelect>

Js: 通过 showTable控制表格显隐

//聚焦
const focus = async ({ currentTarget }) => {
    showTable.value = true;
    await getAccountOptions(currentTarget?._value ?? '');
};


//搜索
const search = debounce(async (val) => {
    showTable.value = true;
    await getAccountOptions(val);
}, 500);


//选择数据
const selectData = ({ row }) => {
    if (row) {
        emits('setRow', row);
        showTable.value = false;
    }
};        

 

三、问题描述:

    通过在几个方法中增加console.log 发现有些电脑在点击的时候并没有进入selectData。更夸张的是,测试的几台windows电脑,使用鼠标点击可以进入,但是使用触摸板轻触却不行。

 

四、解决思路:

    无奈之下,只能放弃上面的写法,通过select中open属性控制下拉框的开闭。

 

五、修改后的代码:

    select外层增加div, dropdownRender内部增加div,用来控制点击事件,如果open属性为true,并且点击组件外部,就关闭下拉框。

html:

<div ref="selectRef">
        <YdSelect
            :value="value"
            :style="{ width: '100%' }"
            :dropdownStyle="{
                minWidth: '800px',
                padding: 0,
                border: 0,
            }"
            :options="tableData"
            :dropdownMatchSelectWidth="300"
            :open="showTable"
            :allow-clear="isJoint"
            showSearch
            @change="change"
            @focus="focus"
            @search="search"
        >
            <template #dropdownRender>
                <div ref="dropdownRef">
                    <VxeGrid
                        v-bind="gridOptions"
                        ref="accountSearchDownTable"
                        @current-change="selectData"
                    >
                        ...
                    </VxeGrid>
                </div>
            </template>
        </YdSelect>
    </div>

js:增加click监听事件

//聚焦
const focus = async ({ currentTarget }) => {
    console.log('focus');
    showTable.value = true;
    await getAccountOptions(currentTarget?._value ?? '');
};

//搜索
const search = debounce(async (val) => {
    if (!showTable.value) return;
    console.log('search', val);
    await getAccountOptions(val);
}, 500);

//改变
const change = async (val) => {
    if (!val) {
        //针对清空的情况
        emits('setRow', {});
    }
};

//选择数据
const selectData = ({ row }) => {
    if (row) {
        emits('setRow', row);
        showTable.value = false;
    }
};// 点击外部关闭下拉的处理函数
const dropdownRef = ref<HTMLElement | null>(null);
const selectRef = ref<HTMLElement | null>(null);
const handleClickOutside = (event: MouseEvent) => {
    if (!showTable.value) return;
    const target = event.target as Node;
    const isInsideContainer = dropdownRef.value?.contains(target);
    const isInsideSelect = selectRef.value?.contains(target);
    console.log(isInsideContainer, isInsideSelect);
    // 如果点击发生在组件外部
    if (!isInsideContainer && !isInsideSelect) {
        showTable.value = false;
    }
};

// 组件卸载时移除监听
onBeforeUnmount(() => {
    document.removeEventListener('click', handleClickOutside);
});

// 添加全局点击事件监听
onMounted(async () => {
    await getAccountOptions();
    document.addEventListener('click', handleClickOutside);
});

 

posted on 2025-06-25 13:50  浅悠  阅读(161)  评论(0)    收藏  举报