80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
import type { PropType } from 'vue'
|
|
import { computed, defineComponent } from 'vue'
|
|
import { getPrefixCls } from '../_utils/getPrefixCls'
|
|
import Icon from '../icon'
|
|
|
|
export default defineComponent({
|
|
name: 'Button',
|
|
props: {
|
|
type: {
|
|
type: String as () => 'solid' | 'outline' | 'text' | 'dashed',
|
|
default: 'solid',
|
|
},
|
|
status: {
|
|
type: String as () => 'primary' | 'danger' | 'warning' | 'success' | 'default',
|
|
default: 'default',
|
|
},
|
|
disabled: { type: Boolean, default: false },
|
|
loading: { type: Boolean, default: false },
|
|
icon: { type: String, default: '' },
|
|
iconPosition: { type: String as () => 'left' | 'right', default: 'left' },
|
|
size: { type: String as () => 'small' | 'medium' | 'large', default: 'medium' },
|
|
block: { type: Boolean, default: false },
|
|
onClick: { type: Function as PropType<(event: MouseEvent) => void> }, // 注意这里不要加 ?
|
|
},
|
|
setup(props, { slots }) {
|
|
const prefixCls = getPrefixCls('btn')
|
|
|
|
const cls = computed(() => [
|
|
prefixCls,
|
|
`${prefixCls}-${props.type}`,
|
|
`${prefixCls}-status-${props.status}`,
|
|
`${prefixCls}-${props.size}`,
|
|
props.block && `${prefixCls}-block`,
|
|
])
|
|
|
|
const iconSize = computed(() => {
|
|
const map = { small: 14, medium: 16, large: 16 }
|
|
return map[props.size]
|
|
})
|
|
const hasContent = !!slots.default?.().length
|
|
|
|
return () => {
|
|
return (
|
|
<button
|
|
class={cls.value}
|
|
disabled={props.disabled || props.loading}
|
|
onClick={props.onClick}
|
|
>
|
|
{props.iconPosition === 'left' && (props.loading || props.icon) && (
|
|
<Icon
|
|
icon={props.loading ? 'mingcute:loading-line' : props.icon}
|
|
class={[
|
|
`${prefixCls}-icon-left`,
|
|
hasContent ? `${prefixCls}-icon-left-has-text` : '',
|
|
]}
|
|
spin={props.loading}
|
|
size={iconSize.value}
|
|
/>
|
|
)}
|
|
|
|
<span>
|
|
{slots.default?.()}
|
|
</span>
|
|
|
|
{props.iconPosition === 'right' && props.icon && (
|
|
<Icon
|
|
icon={props.icon}
|
|
class={[
|
|
`${prefixCls}-icon-right`,
|
|
hasContent ? `${prefixCls}-icon-right-has-text` : '',
|
|
]}
|
|
size={iconSize.value}
|
|
/>
|
|
)}
|
|
</button>
|
|
)
|
|
}
|
|
},
|
|
})
|