模拟封装一个基础组件,包含
一个 base 事件,一个 title 属性,
默认插槽和 foote r插槽
暴漏 close open 方法
x-base
<script lang="ts" setup>
defineProps<{ title: string }>();
const emit = defineEmits<{
base: [];
}>();
function close() {
console.log("close");
}
function open() {
console.log("open");
}
defineExpose({ close, open });
</script>
<template>
<div>
<h2 @click="emit('base')">{{ title }}</h2>
<div class="default"><slot></slot></div>
<div class="footer"><slot name="footer" msg="base组件 footer 插槽内容"></slot></div>
</div>
</template>
<style lang="scss" scoped></style>
基于 x-base 组件二次封装演示
x-test
<script lang="ts">
import { useSlots, onMounted, ref, defineComponent } from "vue";
import xBase from "../x-base/index.vue";
export default defineComponent({
mounted() {
for (const key in this.$refs.baseRef) {
this[key] = this.$refs.baseRef[key];
}
},
});
</script>
<template>
<div>
<x-base v-bind="$attrs" ref="baseRef">
<!-- <template></template> -->
<!-- <template #footer="scope"></template> -->
<template v-for="(value, key) in $slots" :key="key" #[key]="scope">
<slot :name="key" v-bind="scope"></slot>
</template>
</x-base>
</div>
</template>
<style lang="scss" scoped></style>
<script lang="ts" setup>
import { ref } from "vue";
import xTest from "./components/x-test/index.vue";
const xTestRef = ref<InstanceType<typeof xTest> | null>(null);
function close() {
xTestRef.value?.close();
}
</script>
<template>
<x-test title="base" @base="console.log(123)" ref="xTestRef">
<template #default>default</template>
<template #footer="scope">footer--{{ scope }}</template>
</x-test>
<button @click="close">关闭</button>
</template>
<style lang="scss" scoped></style>
$attrs
一个包含了组件所有透传 attributes 的对象。
透传 Attributes 是指由父组件传入,且没有被子组件声明为 props 或是组件自定义事件的 attributes 和事件处理函数。
<x-base v-bind="$attrs"></x-base>
$slots
一个表示父组件所传入插槽的对象。
对象 key 即是插槽名称
<x-base v-bind="$attrs">
<!-- <template #default></template> -->
<!-- <template #footer="scope"></template> -->
// 参照上面写法容易理解
<template v-for="(value, key) in $slots" :key="key" #[key]>
<slot :name="key"></slot>
</template>
</x-base>
作用域插槽
<x-base v-bind="$attrs">
<template v-for="(value, key) in $slots" :key="key" #[key]="scope">
<slot :name="key" v-bind="scope"></slot>
</template>
</x-base>
<x-base v-bind="$attrs" ref="baseRef"></x-base>
export default defineComponent({
mounted() {
for (const key in this.$refs.baseRef) {
this[key] = this.$refs.baseRef[key];
}
},
});
使用
<script lang="ts" setup>
import { ref } from "vue";
import xTest from "./components/x-test/index.vue";
const xTestRef = ref<InstanceType<typeof xTest> | null>(null);
function close() {
xTestRef.value?.close();
}
</script>
<template>
<x-test title="base" @base="console.log(123)" ref="xTestRef">
<template #default>default</template>
<template #footer="scope">footer--{{ scope }}</template>
</x-test>
<button @click="close">关闭</button>
</template>
<style lang="scss" scoped></style>