Skip to main content

TS 在 Vue 中的应用

一、Vue 搭配 TS 应用

二、示例

1、Vue 模板 TS

<template>
<button :class="cls" @click="handleClick">
<i-icon class="i-button-icon" v-if="!!icon" :name="icon" />
<slot />
</button>
</template>

<script setup lang="ts">
import { computed } from 'vue'

interface ButtonProps {
/**
* 是否聚焦状态
* @default false
*/
active?: boolean
/**
* 是否禁用按钮
* @default false
*/
disabled?: boolean
/**
* 按钮形状
* @default round
*/
shape?: 'square' | 'round' | 'circle'
/**
* 按钮尺寸
* @default medium
*/
size?: 'small' | 'medium' | 'large'
/**
* 按钮类型,用于描述组件不同的应用场景
* @default primary
*/
type?: 'info' | 'primary' | 'error' | 'warning' | 'success'
/**
* 按钮形式
* @default base
*/
variant?: 'base' | 'outline' | 'dashed' | 'text'
/**
* 内置图标
*/
icon?: string
}

interface ButtonEmits {
/**
* 点击事件
*/
(type: 'click', e: MouseEvent): void
}

const {
active = false,
disabled = false,
shape = 'round',
size = 'medium',
type = 'primary',
variant = 'base',
icon
} = defineProps<ButtonProps>()
const emit = defineEmits<ButtonEmits>()

const handleClick = (e: MouseEvent) => {
if (disabled) {
return
}
emit('click', e)
}

const cls = computed(() => [
'i-button',
`i-button--type-${type}`,
variant !== 'base' && `i-button--variant-${variant}`,
size !== 'medium' && `i-button--size-${size}`,
shape !== 'round' && `i-button--shape-${shape}`,
active && 'i-button-active',
disabled && 'i-button-disabled'
])
</script>

<style lang="scss">
@import './index.scss';
</style>

2、Vue-JSX TS

import { defineComponent, PropType } from 'vue';
import './index.scss';
import { DropdownOption } from './type'
import { turnValue } from '../common'
import _ from 'lodash';

export default defineComponent({
name: 'DropdownMenu',
props: {
/**
* 下拉操作项
* @default []
*/
options: {
type: Array as PropType<DropdownOption[]>,
default: []
},
/**
* 下拉列表宽度
*/
width: [String, Number],
/**
* 下拉项高度
* @default medium
*/
size: String as PropType<'small' | 'medium' | 'large'>,
/**
* 级联子层级展开方向
* @default right
*/
cascaderDirection: {
type: String as PropType<'left' | 'right'>,
default: 'right'
},
/**
* 是否可多选
* @default false
*/
multiple: {
type: Boolean,
default: false
},
/**
* 选中值
*/
selectedValue: {
type: [String, Number, Array] as PropType<
string |
number |
Array<string | number>
>,
default: []
}
},
emits: {
/**
* 点击菜单项触发事件
*/
'clickItem': (dropdownItem: DropdownOption, event: MouseEvent) => true
},
setup(props, { slots, emit }) {
const handleItemClick = (item: DropdownOption, event: MouseEvent) => {
event.stopPropagation()
!(item.children && item.children?.length > 0) && emit('clickItem', item, event)
item.onClick?.(item, event)
}

return () => {
return (
<ul
class={[
'i-dropdown__menu',
props.cascaderDirection === 'left' && 'i-dropdown__menu-left'
]}
style={{
width: turnValue(props.width) ? turnValue(props.width) : 'auto',
overflowY: props.maxHeight ? 'auto' : 'unset'
}}
>
...
</ul>
);
};
},
});