实战篇笔记-山竹记账前端(三)


封装 WelcomeLayout 组件

目的:消除重复

四个页面只有图片、文字不同,布局结构是一致的

重构前

// src/components/welcome/First.tsx
import { defineComponent } from 'vue';
import s from './First.module.scss';
import pig from '../../assets/icons/pig.svg';
import { RouterLink } from 'vue-router';
export const First = defineComponent({
  setup: (props, context) => {
    return () => (
      <div class={s.wrapper}>
        <div class={s.card}>
          <img src={pig} />
          <h2>会挣钱<br/>还要会省钱</h2>
        </div>
        <div class={s.actions}>
          <RouterLink class={s.fake} to="/start" >跳过</RouterLink>
          <RouterLink to="/welcome/2" >下一页</RouterLink>
          <RouterLink to="/start" >跳过</RouterLink>
        </div>
      </div>
    )
  }
})

重构后

将布局封装为一个组件,内容通过插槽来传入

// src/components/welcome/WelcomeLayout.tsx
import { defineComponent } from 'vue';
import s from './First.module.scss';
export const WelcomeLayout = defineComponent({
  setup: (props, context) => {
    const {slots} = context
    return () => (
      <div class={s.wrapper}>
        <div class={s.card}>
          {slots.icon?.()} 
          {slots.title?.()}
        </div>
        <div class={s.actions}>
          {slots.buttons?.()}
        </div>
      </div>
    )
  }
})
/* 还可以写成函数组件形式
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>
  )
}
*/
// src/components/welcome/First.tsx
import { defineComponent } from 'vue';
import s from './First.module.scss';
import pig from '../../assets/icons/pig.svg';
import { WelcomeLayout } from './WelcomeLayout'
import { RouterLink } from 'vue-router';
export const First = defineComponent({
  setup: (props, context) => {
    const slots = {
      icon: () => <img 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}></WelcomeLayout>
      /* 也可以不用 v-slot 这样写
      <WelcomeLayout>
      {{
        icon: () => <img src={pig} />,
        title: () => <h2>会挣钱<br />还会省钱</h2>,
        buttons: () => <>
            <RouterLink class={s.fake} to="/start" >跳过</RouterLink>
            <RouterLink to="/welcome/2" >下一页</RouterLink>
            <RouterLink to="/start" >跳过</RouterLink>
        </>
      }}
      </WelcomeLayout>
      */
    )
  }

  /* 还可以写成函数组件形式
  export const First: FunctionalComponent = () => {
    return <WelcomeLayout>{{
        icon: () => <img 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'
  */
})

文章作者: April-cl
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 April-cl !
  目录