基于vue3+ts+vant4封装按钮组件
自我记录
src/components/CpRadioBtn.vue
<script setup lang="ts">
defineProps<{
options: {
label: string
value: string | number
}[] // 使用传入数组的方式动态展示需要显示的按钮
modelValue?: string | number // 默认选中 可不传也就是不选
}>()
const emit = defineEmits<{
(e: 'update:modelValue', value: string | number): void
}>()
const toggleItem = (value: string | number) => {
// 触发自定义事件把数据给父组件
emit('update:modelValue', value)
}
</script>
<template>
<div class="cp-radio-btn">
<a
class="item"
href="javascript:;"
v-for="item in options"
:key="item.value"
:class="{ active: modelValue === item.value }"
@click="toggleItem(item.value)"
>
{{ item.label }}
</a>
</div>
</template>
<style lang="scss" scoped>
.cp-radio-btn {
display: flex;
flex-wrap: wrap;
.item {
height: 32px;
min-width: 60px;
line-height: 30px;
padding: 0 14px;
text-align: center;
border: 1px solid #f6f7f9;
background-color: #f6f7f9;
margin-right: 10px;
box-sizing: border-box;
color: #3c3e42;
margin-bottom: 10px;
border-radius: 4px;
transition: all 0.3s;
&.active {
border-color: #16c2a3;
background-color: #eaf8f6;
}
}
}
</style>
添加Ts类型提示
src/types/components.d.ts
// 给components 下的全局组件设置类型
// 1. 导入组件实例
import CpRadioBtn from '@/components/CpRadioBtn.vue'
// 2. 声明 vue 类型模块
declare module 'vue' {
// 3. 给 vue 添加全局组件类型,interface 和之前的合并
interface GlobalComponents {
// 指定组件类型,typeof(从一个JS对象中得到他对应的TS类型) 从组件对象得到类型,设置给全局组件 CpNavBar
CpRadioBtn: typeof CpRadioBtn
}
}
使用src/views/User/index.vue
<script setup lang="ts">
import { ref } from 'vue'
// 传参的数组
const options = [
{ label: '男', value: 1 },
{ label: '女', value: 0 }
]
// 默认选中
const gender = ref(1)
</script>
<template>
<!-- v-model语法糖 -->
<cp-radio-btn :options="options" v-model="gender" />
<!-- 不默认选中的 -->
<cp-radio-btn :options="options" />
<!-- 不使用 v-model 实现父子数据同步,理解语法糖 -->
<cp-radio-btn
:options="options"
:modelValue="gender"
@update:model-value="gender =$event" />
</template>
效果