Vue+Vant封装通用模态框单选框组件
前言
我们知道,在vant组件中提供的组件往往是比较基础的,能够满足基本需求。但是我们想实现ui设计的一些比较丰富效果的组件,需要自己去实现,且当项目中多次用到的时候,我们将以组件化的思想将其封装起来,供各个页面方面使用。
vant提供的单选框效果:
项目中UI提供的单选框效果图
1.右边显示单选框效果
2.右边显示为图标效果
情况
实现思路
在组建中定义如下变量,用来接收父组件传的值
定义props值
- title:标题
- showList:展示列表的数据
- actionVal:当前列表数据中被选中的值
- dialogType:弹框的类型(0-列表 文字 图标;1-列表 文字 radio;2-自动以内容)
- onlyCancel:是否只显示取消按钮,true只显示取消按钮,false:既显示取消按钮,又显示确定按钮。因为有些是需要点击单选框某项之后直接关闭模态框触发回传事件,有些是需要点击确定按钮再触发,所以这里做了一个区分
定义点击事件
1.列表项点击事件:listClick(i)
listClick(i){// 这个key值也是根据父组件传递过来的列表,key值是每项的唯一标识值,这个唯一标示值根据自身业务逻辑而定this.currActionVal=i.key//存储当前最新值this.$emit('update',this.currentActionVal);//这里可以稍微优化,若存在确定按钮,这一步在确定事件中再进行setTimeout(()=>{this.show=false},500)
}
2.点击确定按钮事件:handleConfirm
handleConfirm(){this.$emit('update',this.currentActionVal)
}
3.点击取消事件:handleCancel
handleCancel(){this.$emit('cancel',this.currentActionVal,this.actionVal);//回传旧值和新值,若用户没有触发修改事件时,这里currentActionVal和this.actionVal相等
}
父组件调用
引入与注册
使用
右边显示为图标效果
// html<bottomDialogref="actionDialog":title="$t('hvac.actionModel')":onlyCancel="true":showList="actionIcon":actionVal="action":dialogType="0"@update="actionUpdate($event)"@cancel="actionCancel(arguments)"></bottomDialog>
右边显示为radio效果
最后,附上封装的组件的代码
<template><div><van-dialogv-model="show":title="currTitle":confirmButtonText="$t('common.ensure')"confirmButtonColor="#FEB946":cancelButtonText="$t('common.cancel')"cancelButtonColor="#666666":showCancelButton="true":showConfirmButton="showConfirmFlag"@confirm="handleConfirm"@cancel="handleCancel"><!-- 列表 文字-图标 --><div class="list-container" v-if="Number(dialogType) === 0"><divclass="list-box"v-for="(i, k) in showList":key="k"@click="listClick(i)"><divclass="item-right no-action-font":class="{ 'smartOrange-color': i.key === currActionVal }">{{ i.title }}</div><div class="item-left" :class="i.class"></div></div></div><!-- 列表radio 文字-radio --><div class="list-container" v-if="Number(dialogType) === 1"><van-radio-group v-model="currActionVal"><div class="list-box" v-for="(i, k) in showList" :key="k"><divclass="item-right no-action-font":class="{ 'smartOrange-color': i.key === currActionVal }">{{ i.title }}</div><div class="item-left"><van-radio :name="i.key"><template #icon="props"><divclass="item-left":class="props.checked ? 'radio-icon-orange' : 'radio-icon-grey'"></div></template></van-radio></div></div></van-radio-group></div><!-- 自定义内容 --><div class="list-container" v-if="Number(dialogType) === 2"><slot name="default"></slot></div></van-dialog></div>
</template><script>
import { Dialog, RadioGroup, Radio } from "vant";
export default {name: "bottomDialog",components: {Dialog,RadioGroup,Radio,},props: {// 标题title: {type: String,default: "123",},// 是否只显示取消按钮 -true 只有取消按钮 -false 有取消、确定按钮onlyCancel: {type: Boolean,default: false,},// 展示列表数据showList: {type: Array,default() {return [];},required: false,},// 当前列表数据中被选中的值actionVal: {type: Number,default: 0,required: false,},// 弹窗的类型// 0-列表 文字-图标// 1-列表radio 文字-radio// 2-自定义内容dialogType: {type: Number,default: 0,},},data() {return {show: false,currTitle: this.title,showConfirmFlag: !this.onlyCancel,currActionVal: this.actionVal,};},computed: {},watch: {},created() {},mounted() {},methods: {// 点击确定按钮事件handleConfirm() {console.log(this.currActionVal);this.$emit("update", this.currActionVal);},// 点击取消按钮事件handleCancel() {console.log("newVal:" + this.currActionVal);console.log("oldVal:" + this.actionVal);this.$emit("cancel", this.currActionVal, this.actionVal);},// 列表-图标点击事件listClick(i) {this.currActionVal = i.key;this.$emit("update", this.currActionVal);setTimeout(() => {this.show = false;}, 500);},},
};
</script><style lang="scss" scoped>
.list-container {padding: 20px 40px;.list-box {display: flex;flex-direction: row;justify-content: space-between;align-items: center;.item-left {width: 30px;height: 30px;}}
}
// 重写vant弹窗初始样式
.van-dialog {position: fixed !important;top: auto !important;left: 50% !important;bottom: 60px !important;transform: translateX(-50%) !important;
}
.van-dialog__header {font-size: 18px !important;color: #feb946 !important;font-weight: 600 !important;
}
::v-deep .van-radio__icon{height: 100%;
}
.van-radio{height: 100%;
}
.van-radio__icon {height: 30px !important;
}
</style>