创建 Button 组件
“透传 attribute”指的是传递给一个组件,却没有被该组件声明为 props 或 emits 的 attribute 或者 v-on 事件监听器。最常见的例子就是 class、style 和 id。
当一个组件以单个元素为根作渲染时,透传的 attribute 会自动被添加到根元素上。
// src/shared/Button.tsx
...
// 这里定义接口是因为 TS 错误提示
interface Props{
onClick: (e: MouseEvent) => void
}
export const Button = defineComponent<Props>({
setup: (props, context) => {
return () => (
<button class={s.button}>
{context.slots.default?.()}
</button>
)
}
})
// src/views/StartPage.tsx
...
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> // Button 组件并没有声明 props,点击按钮也可以执行 onClick 事件
</div>
</div>
)
}
})
创建 FloatButton 和 Icon 组件
FloatButton 组件调用 Icon 组件
// src/shared/FloatButton.tsx
...
export const FloatButton = defineComponent({
setup: (props, context) => {
return () => (
<div class={s.floatButton}>
<Icon name="add" class={s.icon}/>
</div>
)
}
})
封装 Icon 组件
- 虽然声明了 Props,TypeScript 转译成 JavaScript 后声明信息就消失了
// src/shared/Icon.tsx
...
interface Props{
name: 'add' | 'chart' | 'clock' | 'cloud' | 'mangosteen' | 'pig'
}
export const Icon = defineComponent<Props>({
setup: (props, context) => {
console.log(props.name) // undefined
return () => (
<svg class={s.icon}>
<use xlinkHref={'#' + props.name}></use>
</svg>
)
}
})
- 声明运行时的 props,会提示
没有与此调用匹配的重载
,查看 defineComponent 声明可知<Props>
和props
不能共存
interface Props{
name: 'add' | 'chart' | 'clock' | 'cloud' | 'mangosteen' | 'pig'
}
export const Icon = defineComponent<Props>({
props: ['name'], // 这里会有错误提示
setup: (props, context) => {
console.log(props.name) // undefined
return () => (
<svg class={s.icon}>
<use xlinkHref={'#' + props.name}></use>
</svg>
)
}
})
考虑用 defineProps,结果不行,会有警告 defineProps 是一个仅
<script setup>
中可用的编译宏命令 ,而且 name 是 null 的报错最后选择的是不用
<Props>
,使用 PropType 这个工具类型来标记 props 类型
...
export const Icon = defineComponent({
props: {
name: {
type: String as PropType<'add' | 'chart' | 'clock' | 'cloud' | 'mangosteen' | 'pig'>
}
},
setup: (props, context) => {
return () => (
<svg class={s.icon}>
<use xlinkHref={'#' + props.name}></use>
</svg>
)
}
})
组件需要透传的 attribute 不在根节点,设置 inheritAttrs: false
可以禁用 Attributes 继承。
sass 内置模块用法
@use "sass:color";
.button {
$primary-color: #6b717f;
color: $primary-color;
border: 1px solid color.scale($primary-color, $lightness: 20%);
}