Open
Description
What problem does this feature solve?
It can solve the problem that JSX or H functions are needed to build complex components, which is as flexible as react.
The slot component can respond to external $slots (similar to props, not modifiable), and can also respond to the dynamically set $slots in the component, just like setting data (let's call it $slotsdata, although all $slots actually come from the outside, in essence, it provides a means to dynamically set $slots).
What does the proposed API look like?
<!-- MyComp -->
<template>
<div>
<!-- render aaa slot -->
<slot name="aaa"></slot>
<div v-for="(row, rowIndex) of daat" :key="rowIndex">
<div v-for="(col, colIndex) of columns" :key="colIndex">
<!-- render `label` slot -->
<!-- In fact, the 'label' slot component renders the slots passed to the MyCompItem component -->
<slot :name="col.label" :row="row" :rowIndex="rowIndex" :colIndex="colIndex">{{row[col.prop]}}</slot>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'MyComp',
props: {
daat: Array,
},
data() {
return {
columns: [],
};
},
created() {
// Get default slot vnode
// It is actually the vnode of MyCompItem
const MyCompItemVNode = this.$slots.default();
this.columns = MyCompItemVNode.map((vnode) => {
const componentProps = vnode.componentProps;
const propsData = componentProps.propsData;
// --------------- key point ------------------------
// Slots should be mounted in` vnode.componentProps.$slots',
// there's no need to hang it in` vnode.componentInstance.$slots',
// because it's just a function that generates slots.
// Mounting to componentinstance also has hidden dangers,
// because you must instantiate slots before you can get the $slots function inside slots.
// The hidden danger is that if the internal slots need to pass parameters,
// developers must track the actual parameters passed and pass the default values for the instantiated slots.
// If you don't have to instantiate the slots function inside the vnode of the slots,
// then developers only need to instantiate slots where they use the slots function to avoid this hidden danger.
// slots.xxx In fact, it is equivalent to an attribute, but classified as slots, not props.
const $slots = componentProps.$slots;
// --------------- key point ------------------------
// Set up new slots for the MyComp component through the following API, similar to setting data
// The slot component can respond to both the external incoming $slots and the dynamically added $slotsdata
$slots.default && this.$set(this.$slotsData, propsData.label, $slots.default);
// or
// $slots.default && this.$setSlots(propsData.label, $slots.default);
return propsData;
});
},
};
</script>
<!-- MyCompItem -->
<template>
<div></div>
</template>
<script>
export default {
name: 'MyCompItem',
props: {
label: String,
prop: String,
},
};
</script>
<!-- usage -->
<template>
<div>
<my-comp :daat="daat">
<!-- Render to 'aaa' slot of MyComp -->
<template #aaa>
<div>AAAAAAAA</div>
</template>
<!-- my-comp-item is not actually rendered -->
<my-comp-item label="名称" prop="name"></my-comp-item>
<my-comp-item label="描述" prop="desc">
<!-- It will actually render to the description slot of the MyComp component -->
<template #default={ row, rowIndex, colIndex }>
<div>{{row}}{{rowIndex}}{{colIndex}}</div>
</template>
</my-comp-item>
</my-comp>
</div>
</template>
<script>
import MyComp from './MyComp';
import MyCompItem from './MyCompItem';
export default {
components: {
MyComp,
MyCompItem,
},
data() {
return {
daat: [
{
name: 'vue',
desc: 'mvvm framework'
}
{
name: 'react',
desc: 'mvvm framework too'
}
],
};
},
};
</script>
Metadata
Metadata
Assignees
Labels
No labels
Activity