js递归向下查询元素函数

49 阅读1分钟

先说用来干什么

在vue中封装input组件是常见到不能再常见的事情,有时候我们会使用div对input进行包裹,然后在全局又注册了一个自定义vue指令用来在元素挂载时获取input焦点,但是这时候我们在组件外部编写自定义事件的时候,vue的熟悉穿透会将这个自定义vue指令绑定在div上

--我编写了一个简单的R-input组件

<script setup name="R-input" lang="ts">
</script>
<template>
<div>
    <input/>
</div>
</template>
<script setup lang="ts">
    import RInput from "./R-input.vue"
    const vFocus = {
        mounted(el) {
            //这里的el应该是div,这是vue属性穿透的特性,具体可用去翻文档
            el.focus();//我们需要的是给input聚焦,而非div
        },
    };
</script>	
<template>
<R-input  v-focus/>
</template>

在这里我们可用对这个自定义事件进行改进,

我们可用封装一个递归函数来查询我们想要的元素

/**
 * * 向下查询dom元素
 * @param {HTMLElement} dom html的dom实例
 * @param {string} nodeName  要查找的html节点名
 */
function findElement(dom, nodeName) {
    if (!dom) return resolve;
    if (!dom.length) dom = [dom];
    let resolve = null;
    for (let val of dom) {
        if (val.nodeName.toLowerCase() === nodeName) resolve = val;
        if (resolve) break;
        const doms = val.children;
        if (doms.length) resolve = findElement([...doms], nodeName);
    }
    return resolve;
}

然后由此我们可以这样封装vue自定义事件

<script setup lang="ts">
    import RInput from "./R-input.vue";
    import fidElement from "....."
    const vFocus = {
        mounted(el) {
            fidElement(el)?.focus();
        },
    };
</script>	
<template>
<R-input  v-focus/>
</template>

当然,我明白,我们可以将自定义指令封装在R-input里面,但是谁又没有遇到过一些意外的尴尬场景呢?