组件封装与插槽
Vue的template一般使用slot,但tsx中的写法有点不同,具体可以查看babel-plugin-jsx。
插槽有多种写法如下所示:
- 案例一
tsx
import { defineComponent } from 'vue';
import s from './First.module.scss';
export const WelcomeLayout = defineComponent({
setup: (props, context) => {
const { slots: { icons, title, buttons } } = context
return () => (
<div class={s.wrapper}>
<div class={s.card}>
{ icons?.() }
{ title?.() }
</div>
<div class={s.actions}>
{ buttons?.() }
</div>
</div>
)
}
})
tsx
import s from './First.module.scss';
import pig from '../../assets/icons/pig.svg';
import { RouterLink } from 'vue-router';
import { WelcomeLayout } from './WelcomeLayout';
import { defineComponent } from 'vue';
export const First = defineComponent({
setup: (props, context) => {
const slots = {
icon: () => <img class={s.pig} src={pig} />,
title: () => <h2>会挣钱<br />还要会省钱</h2>,
buttons: () => <>
<RouterLink class={s.fake} to="/start" >跳过</RouterLink>
<RouterLink to="/welcome/2" >下一页</RouterLink>
<RouterLink to="/start" >跳过</RouterLink>
</>
}
return () => <WelcomeLayout v-slots={slots}/>
}
})
tsx
import { defineComponent } from 'vue'
import s from './First.module.scss';
import chart from '../../assets/icons/chart.svg'
import { RouterLink } from 'vue-router'
import { WelcomeLayout } from './WelcomeLayout'
export const Third = defineComponent({
setup: (props, context) => {
return () => (
<WelcomeLayout>
{{
icon: () => <img class={s.icon} src={chart} />,
title: () => <h2>每日提醒<br />不遗漏每一笔账单</h2>,
buttons: () => <>
<RouterLink class={s.fake} to="/start" >跳过</RouterLink>
<RouterLink to="/welcome/4" >下一页</RouterLink>
<RouterLink to="/start" >跳过</RouterLink>
</>
}}
</WelcomeLayout>
)
}
})
- 案例二,最终采用这种方法重构
tsx
import { FunctionalComponent } from 'vue';
import s from './WelcomeLayout.module.scss';
export const WelcomeLayout: FunctionalComponent = (props, context) => {
const { slots: { icon, title, buttons } } = context
return (
<div class={s.wrapper}>
<div class={s.card}>
{icon?.()}
{title?.()}
</div>
<div class={s.actions}>
{buttons?.()}
</div>
</div>
)
}
tsx
import s from './WelcomeLayout.module.scss';
import pig from '../../assets/icons/pig.svg';
import { RouterLink } from 'vue-router';
import { WelcomeLayout } from './WelcomeLayout';
import { FunctionalComponent } from 'vue';
export const First: FunctionalComponent = () => {
return <WelcomeLayout>
{{
icon: () => <img class={s.pig} src={pig} />,
title: () => <h2>会挣钱<br />还要会省钱</h2>,
buttons: () => <>
<RouterLink class={s.fake} to="/start" >跳过</RouterLink>
<RouterLink to="/welcome/2" >下一页</RouterLink>
<RouterLink to="/start" >跳过</RouterLink>
</>
}}
</WelcomeLayout>
}
First.displayName = 'First'