为什么要二次封装UI组件库?

因为业务场景需求现有组件库不满足,需要自己二次封装改造

二次封装UI组件库要考虑哪些东西?

1. UI组件本身的属性以及事件的问题;
2. 组件提供的插槽问题;
UI组件本身的属性以及事件的问题

以Vue3为例,在Vue3中有一个属性名为 $attrs , $attrs 这个属性是一个对象,它能拿到除了属性定义之外
的,所有的其他传递字段

举🌰
// 子组件
<template>
  <div class="customInput">
    <el-input placeholder="请输入内容" v-bind="$attrs"></el-input>
  </div>
</template>
<script>
export default {
    created() {
        console.log(this.$attrs)
    }
};
</script>
<style scoped>
.customInput{
    transition: 0.3s;
}
</style>
// 父组件
<template>
  <div class="customInput">
    <customInput v-model="val"></customInput>
  </div>
</template>
<script setup>
export default {
    import customInput from './components/customInput.vue';
    const val = ref('')
};
</script>

运行之后看浏览器控制台输出结果:
运行结果

从控制台可以看出 $attrs 输出结果有两个,一个是 modelValue, 则一个是事件,于是第一个问题就通过属性的穿透实现

组件提供的插槽问题

为了避免UI组件库的插槽有不同处理事件,因此我们不能将插槽写死,需要动态生成,也是通过一个属性 $slots 实现;
$slots 打印结果:
$slots的打印结果

通过结果可以看出,$slots 是一个对象,而一个属性带代表父组件传递一个插槽,并且截图发现插槽在JS中本质上也是一个函数,并且一个属性名就是一个插槽的名字

实现方法举个🌰
// 子组件
<template>
  <div class="customInput">
    <el-input placeholder="请输入内容" v-bind="$attrs">
        <template v-for="(value, name) in $slots" #[name]="scopeData">
            <slot :name="name" v-bind="scopeData || {}"></slot>
        </template>
    </el-input>
  </div>
</template>
<script>
export default {
    created() {
        console.log(this.$slots)
    }
};
</script>
<style scoped>
.customInput{
    transition: 0.3s;
}
</style>
// 父组件
<template>
  <div class="customInput">
    <customInput v-model="val">
        <template #append>
            <el-button :icon="Search"></el-button>
        </template>
    </customInput>
  </div>
</template>
<script setup>
export default {
    import customInput from './components/customInput.vue';
    const val = ref('')
};
</script>