先说用来干什么
在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里面,但是谁又没有遇到过一些意外的尴尬场景呢?