Skip to content

业务与轮子的关系

可以从原型内容内拆分相同的内容,然后在去造轮子。首先很多AntD或ElementUI大部分不能满足要求,其次可能需要基于这些UI来进行二次封装,以达到满足公司的需求。造轮子的好处:通过学习新的开源轮子,发现和不适合公司业务的地方,自己缝合一套适合公司业务的轮子。

根据设计稿写了如下几个轮子。

Button组件

为了方便导入组件的样式,配置snippet的代码模版。

json
{
  "Import Module SCSS":{
    "prefix": "ims",
    "body": [
      "import 's' from './$1.module.scss;"
    ]
  }
}

由于button标签有历史遗留的bug,使用width: 100%; margin: 16px,会导致button的内容超出,解决方法一般在button外面再套一个容器。

尤大大的Vue3相当于是React的升级版,他将一些属性进行了处理,将一些原生属性进行了处理,直接继承了,可以直接使用,也可以通过inheritAttrs将这些继承的属性给关闭,转而使用props来自己全全处理。

denfineComponent(...)还需配置接受TS类型,内部接受JS。

tsx
import { defineComponent } from 'vue'
import s from './Button.module.scss'
interface Props  {
  onClick: (e: MouseEvent) => void
}

export const Button = defineComponent<Props>({
  setup: (props, context) => {
    return () => (
      <button class={s.button}>
        {context.slots.default?.()}
      </button>
    )
  }
})
tsx
import { defineComponent } from 'vue'
import s from './Button.module.scss'
interface Props  {
  onClick: (e: MouseEvent) => void
}
export const Button = defineComponent<Props>({
  inheritAttrs: false,
  props: ['class','onClick'],
  setup: (props, context) => {
    return () => (
      <button class={[s.button, props.class]} onClick={props.onClick}>
        {context.slots.default?.()}
      </button>
    )
  }
})

在StartPage页面中使用,并在router.tsx内添加了路由{path:'/start', component:StartPage}

tsx
import { defineComponent } from 'vue';
import { Button } from '../shared/Button';
import s from './StartPage.module.scss';
export const StartPage = defineComponent({
  setup: (props, context) => {
    const onClick = () => {
      console.log('hi')
    }
    return () => (
      <div>
        <div class={s.button_wrapper}>
          <Button class={s.button} onClick={onClick}>测试</Button>
        </div>
      </div>
    )
  }
})

Icon组件

为了方便使用svg文件创建了Icon组件。然后将下载好的svg文件放在oh-my-env提前设置好的temp文件夹内在终端执行mv /workspaces/oh-my-env/temp/*.svg src/assets/icons/,将文件放置容器中。

传入props的时候需要对props的参数进行类型定义,通过defineComponent<Props>进行类型定义的话,会出现类型重载的现象,如果是在<script setup>下可以使用defineProps(),于是采用下种写法,小的props更为适用。

tsx
import { defineComponent, PropType } from 'vue'
import s from './Icon.module.scss'
export type IconName = 'add' | 'chart' | 'clock' | 'cloud' | 'mangosteen' | 'pig'

export const Icon = defineComponent({
  props: {
    name: {
      type: String as PropType<IconName>,
      required: true
    }
  },
  setup: (props, context) => {
    return () => (
      <svg class={s.icon}>
        <use xlinkHref={'#' + props.name}/>
      </svg>
    )
  }
})
css
.icon {
  width: 1.2em;
  height: 1.2em;
}

为了方便创建代码模版可以带有props的代码模版。

json
{
    "Vue Component With Props":{ 
		"prefix": "vcp",
		"body": [
		"import { defineComponent, PropType } from 'vue'",
		"export const $1 = defineComponent({",
		"  props: {",
		"    $2: {",
		"      type: $3 as PropType<$4>",
		"    }",
		"  },",
    "  setup: (props, context) => {",
    "    return () => (",
    "      <div>$5</div>",
		"    )",
		"  }",
		"})",
		]	
	},
}

FloatButton组件

设置悬浮button,使用fixed布局。

tsx
import { defineComponent, PropType } from 'vue';
import { Icon, IconName } from './Icon';
import s from './FloatButton.module.scss';
export const FloatButton = defineComponent({
  props: {
    iconName: {
      type: String as PropType<IconName>,
      required: true
    }
  },
  setup: (props, context) => {
    return () => (
      <div class={s.floatButton}>
        <Icon name={props.iconName} class={s.icon}/>
      </div>
    )
  }
})

可以在scss内使用math的方法,详细见链接

css
@use 'sass:math';
/* 适用math的写法可以在css内进行计算 */
.floatButton {
  background: var(--float-button-bg);
  width: 56px;
  height: 56px;
  border-radius: 50%;
  // border-radius: math.div(56px,2);
  display: flex;
  justify-content: center;
  align-items: center;
  position: fixed;
  bottom: 16px;
  right: 16px;

  .icon {
    width: 24px;
    height: 24px;
    fill: var(--float-button-text);
  }
}