二次封装原则:
-
不改变原有组件的接口,即保持原有组件提供的接口 属性、方法、事件、插槽
属性透传 v-bind=“$attrs”
inheritAttrs 默认情况下,父组件传递的,但没有被子组件解析的props的attributes绑定会被透传(这意味着当我们有一个单根节点的子组件时,这些绑定会被作为一个常规的 HTML attribute 应用在子组件的根节点元素上)
-
继承第三方组件的 Event 事件
v-on=“$listeners”
-
使用第三方组件的 Slots
-
使用第三方组件的methods
可以将组件提供方法提取到实例上
<template>
<div class="my-input">
<!-- 属性透传 -->
<el-input v-bind="$attrs" v-on="$listeners">
<!-- 遍历子组件非作用域插槽,并对父组件暴露 -->
<template v-for="(index, name) in $slots" v-slot:[name]>
<slot :name="name" />
</template>
<!-- 遍历子组件作用域插槽,并对父组件暴露 -->
<template v-for="(index, name) in $scopedSlots" v-slot:[name]="data">
<slot :name="name" v-bind="data"></slot>
</template>
</el-input>
<!-- 在 Vue3 中,取消了$listeners这个组件实例的属性,将其事件的监听都整合到了$attrs上 -->
<!-- 因此直接通过v-bind=$attrs属性就可以进行props属性和event事件的透传 -->
<!-- 在 Vue3 中,取消了作用域插槽 $scopedSlots,将所有插槽都统一在 $slots 当中: -->
<el-input v-bind="$attrs">
<template #[slotName]="slotProps" v-for="(slot, slotName) in $slots">
<slot :name="slotName" v-bind="slotProps"></slot>
</template>
</el-input>
</div>
</template>
<script>
export default {}
</script>
<style></style>
<template>
<div class="my-table">
<el-table ref="el-table"></el-table>
</div>
</template>
<script>
// vue2
export default {
mounted() {
this.extendMethod()
},
methods: {
extendMethod() {
const refMethod = Object.entries(this.$refs['el-table'])
for (const [key, value] of refMethod) {
if (!(key.includes('$') || key.includes('_'))) {
this[key] = value
}
}
}
}
}
</script>
<script setup>
// vue3
import { ref, onMounted } from 'vue'
import { ElTable } from 'element-plus'
const table = ref()
onMounted(() => {
const entries = Object.entries(table.value)
for (const [method, fn] of entries) {
expose[method] = fn
}
})
defineExpose(expose)
</script>