业务与轮子的关系
可以从原型内容内拆分相同的内容,然后在去造轮子。首先很多AntD或ElementUI大部分不能满足要求,其次可能需要基于这些UI来进行二次封装,以达到满足公司的需求。造轮子的好处:通过学习新的开源轮子,发现和不适合公司业务的地方,自己缝合一套适合公司业务的轮子。
根据设计稿写了如下几个轮子。
Button组件
为了方便导入组件的样式,配置snippet的代码模版。
{
"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。
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>
)
}
})
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}
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
更为适用。
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>
)
}
})
.icon {
width: 1.2em;
height: 1.2em;
}
为了方便创建代码模版可以带有props的代码模版。
{
"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布局。
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的方法,详细见链接。
@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);
}
}