实际应用中的例子
import { defineComponent, renderSlot } from "vue";
import type { SetupContext } from "vue";
import utils from "@/utils/index";
const header = defineComponent({
props: {
root: { type: Boolean, default: false }, // 如果为true则调用原生关闭页面
title: { type: String, default: "标题" }, // 标题
leftText: { type: String, default: "返回" }, // 左侧显示
rightText: { type: String, default: "按钮" }, // 右侧按钮
clickLeft: { type: Function, default() {} } // 拦截左侧点击事件,Promise.resove或true时执行返回或关闭
},
setup(props: Readonly<any>, { slots }: SetupContext) {
//! 返回确认
let go = () => {
if (props.root) {
// 调用原生关闭页面
} else {
window.$router.go(-1);
}
};
//! 点击返回
let eventClickLeft = () => {
let fn = props.clickLeft();
if (utils.isType(fn) === "Promise") {
fn.then(() => {
go();
});
} else if (fn === true) {
go();
}
};
// debugger;
return () => (
<header>
<van-nav-bar title={props.title} left-text={props.leftText} right-text={props.rightText} left-arrow onClickLeft={eventClickLeft}>
{/* {{
right: () => (slots["right"] ? slots["right"]() : "")
}} */}
{{
right: renderSlot(slots, "right")
}}
</van-nav-bar>
{renderSlot(slots, "right")}
</header>
);
}
});
export default header;
还有一种简单直观对象注入
执行参数为传入父级的对象
{{
right: () => (slots["right"] ? slots["right"]({data:"test1"}) : "")
}}
vue3中slot注入的方式renderSlot
源码中对其解释,slots 为当前上下文 slots,name为要查找的slot名称,props为传给父级的数据, fallback中判断currentRenderingInstance为上下文具体参见下面ComponentInternalInstance部分代码,使用方式为再setup中通过getCurrentInstance获取当前实例的类型,fallback需返回一个VNodeArrayChildren类型的数组,数组包含getCurrentInstance实例,按说明看不对外开放(看着想是嵌套子集),具体使用方式持续跟进中,noSlotted与上下文ctx相关具体用法跟进中。
function renderSlot(slots, name, props = {},
// this is not a user-facing function, so the fallback is always generated by
// the compiler and guaranteed to be a function returning an array
fallback, noSlotted) {
if (currentRenderingInstance.isCE) {
return createVNode('slot', name === 'default' ? null : { name }, fallback && fallback());
}
let slot = slots[name];
if (slot && slot.length > 1) {
warn(`SSR-optimized slot function detected in a non-SSR-optimized render ` +
`function. You need to mark this component with $dynamic-slots in the ` +
`parent template.`);
slot = () => [];
}
// a compiled slot disables block tracking by default to avoid manual
// invocation interfering with template-based block tracking, but in
// `renderSlot` we can be sure that it's template-based so we can force
// enable it.
if (slot && slot._c) {
slot._d = false;
}
openBlock();
const validSlotContent = slot && ensureValidVNode(slot(props));
const rendered = createBlock(Fragment, { key: props.key || `_${name}` }, validSlotContent || (fallback ? fallback() : []), validSlotContent && slots._ === 1 /* STABLE */
? 64 /* STABLE_FRAGMENT */
: -2 /* BAIL */);
if (!noSlotted && rendered.scopeId) {
rendered.slotScopeIds = [rendered.scopeId + '-s'];
}
if (slot && slot._c) {
slot._d = true;
}
return rendered;
}
export declare interface ComponentInternalInstance {
uid: number;
type: ConcreteComponent;
parent: ComponentInternalInstance | null;
root: ComponentInternalInstance;
appContext: AppContext;
/**
* Vnode representing this component in its parent's vdom tree
*/
vnode: VNode;
/* Excluded from this release type: next */
/**
* Root vnode of this component's own vdom tree
*/
subTree: VNode;
/**
* Render effect instance
*/
effect: ReactiveEffect;
/**
* Bound effect runner to be passed to schedulers
*/
update: SchedulerJob;
/* Excluded from this release type: render */
/* Excluded from this release type: ssrRender */
/* Excluded from this release type: provides */
/* Excluded from this release type: scope */
/* Excluded from this release type: accessCache */
/* Excluded from this release type: renderCache */
/* Excluded from this release type: components */
/* Excluded from this release type: directives */
/* Excluded from this release type: filters */
/* Excluded from this release type: propsOptions */
/* Excluded from this release type: emitsOptions */
/* Excluded from this release type: inheritAttrs */
/**
* is custom element?
*/
isCE?: boolean;
/**
* custom element specific HMR method
*/
ceReload?: (newStyles?: string[]) => void;
proxy: ComponentPublicInstance | null;
exposed: Record<string, any> | null;
exposeProxy: Record<string, any> | null;
/* Excluded from this release type: withProxy */
/* Excluded from this release type: ctx */
data: Data;
props: Data;
attrs: Data;
slots: InternalSlots;
refs: Data;
emit: EmitFn;
/* Excluded from this release type: emitted */
/* Excluded from this release type: propsDefaults */
/* Excluded from this release type: setupState */
/* Excluded from this release type: devtoolsRawSetupState */
/* Excluded from this release type: setupContext */
/* Excluded from this release type: suspense */
/* Excluded from this release type: suspenseId */
/* Excluded from this release type: asyncDep */
/* Excluded from this release type: asyncResolved */
isMounted: boolean;
isUnmounted: boolean;
isDeactivated: boolean;
/* Excluded from this release type: bc */
/* Excluded from this release type: c */
/* Excluded from this release type: bm */
/* Excluded from this release type: m */
/* Excluded from this release type: bu */
/* Excluded from this release type: u */
/* Excluded from this release type: bum */
/* Excluded from this release type: um */
/* Excluded from this release type: rtc */
/* Excluded from this release type: rtg */
/* Excluded from this release type: a */
/* Excluded from this release type: da */
/* Excluded from this release type: ec */
/* Excluded from this release type: sp */
}