单选
单选组件代码如下
<template>
<view>
<view class="titleBox">
<view class="top">
<text class="title">{{ title }}</text>
<text class="remark">已选:{{
chooseRemark
}}</text>
</view>
<view class="search-bar-box-body">
<view class="search-bar-box">
<uni-search-bar v-model="searchVal" bgColor="transparent" cancelButton="none" placeholder="搜索"></uni-search-bar>
</view>
</view>
</view>
<template v-for="item in radiolist">
<view class="item" @click="choose(item)">
{{ item[props.sign] }}
<view class="check" v-if="item.isChoose"> ✓ </view>
<view class="uncheck" v-else> </view>
</view>
</template>
</view>
</template>
<script setup>
import { ref, computed } from "vue";
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
const props = defineProps({
sign: {
//标识,需要显示的字段
type: String,
default: "",
},
});
const title = ref("单选");
const chooseRemark = ref("");
const list = ref([]); //如果包含isChoose=true则为选中
//已选中的list
const chooselist = computed(() => {
return list.value.filter((item) => item.isChoose)[0];
});
//选择
function choose(item) {
list.value.forEach(element => {
element.isChoose = false;
});
item.isChoose = true;
chooseRemark.value = item[props.sign]
}
//筛选
const searchVal = ref();
const radiolist = computed(() => {
if (!searchVal.value) {
return list.value;
}
return list.value.filter((item) =>
item[props.sign].includes(searchVal.value)
);
});
defineExpose({
title,
chooseRemark,
list,
chooselist,
});
</script>
<style scoped lang="scss">
.item:last-child {
border-bottom: 1px solid #fff;
}
.item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
border-bottom: 1px solid rgba(217, 217, 217, 1);
// margin-top:20rpx;
}
.check {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
background: rgba(51, 124, 250, 1);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-weight: 600;
border: 1rpx solid rgba(51, 124, 250, 1);
}
.uncheck {
width: 40rpx;
height: 40rpx;
border-radius: 50%;
border: 1rpx solid rgba(122, 122, 122, 1);
}
.titleBox {
width: 100%;
position: sticky;
top: 0px;
background-color: #fff;
padding-bottom: 20rpx;
.top {
display: flex;
align-items: flex-end;
.title {
font-size: 34.35rpx;
font-weight: 600;
}
.remark {
margin-left: 30rpx;
color: rgba(122, 122, 122, 1);
font-size: 26.71rpx;
}
}
.search-bar-box-body {
padding: 20rpx 0 0;
position: sticky;
top: 0px;
background-color: #fff;
z-index: 9;
:deep {
.uni-searchbar__box {
justify-content: start;
}
.uni-input-placeholder {
color: #b5b5b5;
}
}
.search-bar-box {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 65rpx;
background-color: #f3f5f9;
border-radius: 60rpx;
.uni-searchbar {
flex: 1;
}
.search-btn {
margin-right: 26rpx;
color: $uni-primary;
font-size: 24rpx;
line-height: 24px;
}
}
}
}</style>
使用如下,需要使用到弹窗容器包裹,具体看我以前写的,实现代码及图例如下,根据不同种单选类型二次封装组件,让逻辑部分的代码更加简洁
<template>
<view @click="open()">打开弹窗</view>
<popupBox ref="Popup" :onConfirmDisable="onConfirmDisable">
<template #title> </template>
<template #content>
<popupBox_Content_radio ref="popupBox_Content_radio_Ref" sign="name"></popupBox_Content_radio>
</template>
</popupBox>
</template>
<script setup>
import popupBox from "./components/popupBox";
import popupBox_Content_radio from "./components/popupBox_Content_radio";
import { ref, computed, onMounted, watch, defineEmits } from "vue";
import { onLoad } from "@dcloudio/uni-app";
// 弹窗容器
const Popup = ref(null);
// 单选组件
const popupBox_Content_radio_Ref = ref(null);
// 单选列表
const SelectList = [{ name: "选项1", id: 1, isChoose: true },
{ name: "选项2", id: 1 },
{ name: "选项3", id: 1 },
{ name: "选项4", id: 1 }]
// 已选项
const isSelect = ref(SelectList[0]);
// 是否禁用确认按钮
const onConfirmDisable = computed(() => {
if (!popupBox_Content_radio_Ref.value?.chooselist) {
return true
}
return false
})
function open() {
//打开弹窗
Popup.value.open({
cancelText: "取消",
confirmText: "确认",
onOpen: function () {
//单选标题
popupBox_Content_radio_Ref.value.title = "单选组件标题";
//单选已选
popupBox_Content_radio_Ref.value.chooseRemark = isSelect.value.name;
//单选列表
popupBox_Content_radio_Ref.value.list =JSON.parse(JSON.stringify(SelectList))
},
onConfirm: function () {
//已选项赋值
isSelect.value = popupBox_Content_radio_Ref.value.chooselist
Popup.value.close()//关闭弹窗
},
onClose: function () {
console.log("触发了弹窗《关闭》事件");
},
});
}
</script>
<style lang="scss" scoped></style>
多选
多选组件代码如下
<template>
<view>
<view class="titleBox">
<view class="top">
<text class="title">{{ title }}</text>
<text class="remark"
>已选:{{
chooseRemark || `${chooselist.length}/${list.length}`
}}</text
>
</view>
<view class="search-bar-box-body">
<view class="search-bar-box">
<uni-search-bar
v-model="searchVal"
bgColor="transparent"
cancelButton="none"
placeholder="搜索"
></uni-search-bar>
</view>
</view>
</view>
<template v-for="item in multiplelist">
<view class="item" @click="item.isChoose = !item.isChoose">
{{ item[props.sign] }}
<view class="check" v-if="item.isChoose"> ✓ </view>
<view class="uncheck" v-else> </view>
</view>
</template>
</view>
</template>
<script setup>
import { ref, computed } from "vue";
import { onLaunch, onShow, onHide } from "@dcloudio/uni-app";
const props = defineProps({
sign: {
//标识,需要显示的字段
type: String,
default: "",
},
});
const title = ref("多选");
const chooseRemark = ref("");
const sign = ref("");
const list = ref([]); //如果包含isChoose=true则为选中
//已选中的list
const chooselist = computed(() => {
return list.value.filter((item) => item.isChoose);
});
//选项列表
const searchVal = ref();
const multiplelist = computed(() => {
if (!searchVal.value) {
return list.value;
}
return list.value.filter((item) =>
item[props.sign].includes(searchVal.value)
);
});
defineExpose({
title,
chooseRemark,
list,
chooselist,
});
</script>
<style scoped lang="scss">
.item:last-child {
border-bottom: 1px solid #fff;
}
.item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx 0;
border-bottom: 1px solid rgba(217, 217, 217, 1);
// margin-top:20rpx;
}
.check {
width: 40rpx;
height: 40rpx;
border-radius: 8rpx;
background: rgba(51, 124, 250, 1);
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-weight: 600;
border: 1rpx solid rgba(51, 124, 250, 1);
}
.uncheck {
width: 40rpx;
height: 40rpx;
border-radius: 8rpx;
border: 1rpx solid rgba(122, 122, 122, 1);
}
.titleBox {
width: 100%;
position: sticky;
top: 0px;
background-color: #fff;
padding-bottom: 20rpx;
.top {
display: flex;
align-items: flex-end;
.title {
font-size: 34.35rpx;
font-weight: 600;
}
.remark {
margin-left: 30rpx;
color: rgba(122, 122, 122, 1);
font-size: 26.71rpx;
}
}
.search-bar-box-body {
padding: 20rpx 0 0;
position: sticky;
top: 0px;
background-color: #fff;
z-index: 9;
:deep {
.uni-searchbar__box {
justify-content: start;
}
.uni-input-placeholder {
color: #b5b5b5;
}
}
.search-bar-box {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
height: 65rpx;
background-color: #f3f5f9;
border-radius: 60rpx;
.uni-searchbar {
flex: 1;
}
.search-btn {
margin-right: 26rpx;
color: rgba(51, 124, 250, 1);
font-size: 24rpx;
line-height: 24px;
}
}
}
}
</style>
使用如下,需要使用到弹窗容器包裹,具体看我以前写的,实现代码及图例如下,根据不同种多选类型二次封装组件,让逻辑部分的代码更加简洁
<template>
<view @click="open()">打开弹窗</view>
<popupBox ref="Popup" :onConfirmDisable="onConfirmDisable">
<template #title> </template>
<template #content>
<popupBox_Content_multipleChoice ref="popupBox_Content_multipleChoice_Ref" sign="name"></popupBox_Content_multipleChoice>
</template>
</popupBox>
</template>
<script setup>
import popupBox from "./components/popupBox";
import popupBox_Content_multipleChoice from "./components/popupBox_Content_multipleChoice";
import { ref, computed, onMounted, watch, defineEmits } from "vue";
import { onLoad } from "@dcloudio/uni-app";
// 弹窗容器
const Popup = ref(null);
// 多选组件
const popupBox_Content_multipleChoice_Ref = ref(null);
// 多选列表
const SelectList = [{ name: "选项1", id: 1, isChoose: true },
{ name: "选项2", id: 1 },
{ name: "选项3", id: 1 },
{ name: "选项4", id: 1 }]
// 已选项
const isSelect = ref([SelectList.values[0]]);
// 是否禁用确认按钮
const onConfirmDisable = computed(() => {
if (!popupBox_Content_multipleChoice_Ref.value?.chooselist.length) {
return true
}
return false
})
function open() {
//打开弹窗
Popup.value.open({
cancelText: "取消",
confirmText: "确认",
onOpen: function () {
//多选标题
popupBox_Content_multipleChoice_Ref.value.title = "多选组件标题";
//多选列表
popupBox_Content_multipleChoice_Ref.value.list = JSON.parse(JSON.stringify(SelectList))
},
onConfirm: function () {
//已选项赋值
isSelect.value = popupBox_Content_multipleChoice_Ref.value.chooselist
Popup.value.close()//关闭弹窗
},
onClose: function () {
console.log("触发了弹窗《关闭》事件");
},
});
}
</script>
<style lang="scss" scoped></style>
✓符号 替换
这个✓符号在实际项目运行不好看,可以替换为svg
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="15" height="15" viewBox="0 0 32 32">
<path
d="M1.952 18.080q-0.32-0.352-0.416-0.88t0.128-0.976l0.16-0.352q0.224-0.416 0.64-0.528t0.8 0.176l6.496 4.704q0.384 0.288 0.912 0.272t0.88-0.336l17.312-14.272q0.352-0.288 0.848-0.256t0.848 0.352l-0.416-0.416q0.32 0.352 0.32 0.816t-0.32 0.816l-18.656 18.912q-0.32 0.352-0.8 0.352t-0.8-0.32l-7.936-8.064z"
fill="rgba(51, 124, 250, 1)"
></path>
</svg>
在uniapp使用,具体样式和svg颜色自己改
<image :src="isChoosesvg" mode="widthFix"></image>
import isChoosesvg from "./xxxx.svg";