1
This commit is contained in:
@@ -0,0 +1,190 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch, onMounted, onBeforeUnmount, provide } from "vue"
|
||||
import { getDefaultColor, colorAddDeepen } from "../../core/util/xCoreColorUtil.uts"
|
||||
import { checkIsCssUnit, getUid } from "../../core/util/xCoreUtil.uts"
|
||||
import { xConfig } from "../../config/xConfig.uts"
|
||||
import { CHECKBOX_ITEM_INFO } from '../../interface.uts';
|
||||
|
||||
type XCHECKBOX_LISTITEM_TYPE = {
|
||||
id : string,
|
||||
data : CHECKBOX_ITEM_INFO
|
||||
}
|
||||
|
||||
/**
|
||||
* @name 多选框组 xCheckboxGroup
|
||||
* @page /pages/index/checkbox-group
|
||||
* @category 表单组件
|
||||
* @description 使用时,从1.1.2开始允许是非直接x-checkbox子节点布局,但考虑到性能建议是直接子节点.
|
||||
* @constant 平台兼容
|
||||
* | Harmony | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| ☑ | ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.76+ | 1.1.18 |
|
||||
*/
|
||||
defineOptions({name:"xCheckboxGroup"})
|
||||
|
||||
export type xCheckboxGroupPropsType = {
|
||||
/**
|
||||
* 当前选中的值。
|
||||
*/
|
||||
modelValue: Array<string|number|boolean>,
|
||||
/**
|
||||
* 对齐方式
|
||||
*/
|
||||
direction: "row" | "column",
|
||||
/**
|
||||
* 最大选择数量,-1表示不限制。
|
||||
*/
|
||||
max: number
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<xCheckboxGroupPropsType>(), {
|
||||
modelValue: ():Array<string|number|boolean> => [] as Array<string|number|boolean>,
|
||||
direction: "row",
|
||||
max: -1
|
||||
})
|
||||
|
||||
const emits = defineEmits([
|
||||
/**
|
||||
* 选项变化时触发。
|
||||
* @param {Array<string|number|boolean>} val - 当前选中的值
|
||||
*/
|
||||
'change',
|
||||
'update:modelValue'
|
||||
])
|
||||
|
||||
// 响应式数据
|
||||
const oldvalueList = ref<XCHECKBOX_LISTITEM_TYPE[]>([])
|
||||
const checkvaluelist = ref<Array<string|number|boolean>>([])
|
||||
const tid = ref(0)
|
||||
const isDestroy = ref(false)
|
||||
const id = ref("xCheckboxGroup-" + getUid())
|
||||
|
||||
// 计算属性
|
||||
const oldvalueList_ids = computed((): string[] => {
|
||||
return oldvalueList.value.map((el : XCHECKBOX_LISTITEM_TYPE) : string => el.id)
|
||||
})
|
||||
|
||||
const _max = computed((): number => {
|
||||
return props.max;
|
||||
})
|
||||
|
||||
// 方法
|
||||
//设置当前选中的值
|
||||
function setOldCheckboxValue() {
|
||||
oldvalueList.value.forEach((item : XCHECKBOX_LISTITEM_TYPE) => {
|
||||
if (checkvaluelist.value.includes(item.data.value)) {
|
||||
item.data.nowvalue = item.data.value
|
||||
} else {
|
||||
item.data.nowvalue = item.data.unvalue
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//当前选中的值
|
||||
function getcheckvaluelist() {
|
||||
let fl = oldvalueList.value.filter((el : XCHECKBOX_LISTITEM_TYPE) : boolean => el.data.nowvalue == el.data.value)
|
||||
let allfill = oldvalueList.value.map((el : XCHECKBOX_LISTITEM_TYPE) : string|number|boolean => el.data.value)
|
||||
let realValue = fl.map((el : XCHECKBOX_LISTITEM_TYPE) : string|number|boolean => el.data.value);
|
||||
// 删除已有的,保留差异的。
|
||||
let psdiff = checkvaluelist.value.filter((el : string|number|boolean) : boolean => !allfill.includes(el))
|
||||
|
||||
checkvaluelist.value = realValue.concat(psdiff)
|
||||
}
|
||||
function addItem(item : CHECKBOX_ITEM_INFO, ischange : boolean) {
|
||||
let index = oldvalueList.value.findIndex((el : XCHECKBOX_LISTITEM_TYPE) : boolean => el.id == item.id);
|
||||
let nowitem = item
|
||||
|
||||
let fl = oldvalueList.value.filter((el : XCHECKBOX_LISTITEM_TYPE) : boolean => el.data.nowvalue == el.data.value)
|
||||
|
||||
if (!ischange) {
|
||||
if (checkvaluelist.value.includes(item.value) && item.nowvalue != item.value) {
|
||||
nowitem.nowvalue = nowitem.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (index > -1) {
|
||||
let oldItem = oldvalueList.value[index]
|
||||
if (fl.length >= _max.value && _max.value > -1 && ischange && oldItem.data.nowvalue != oldItem.data.value) {
|
||||
// "已是最大选择数量"
|
||||
uni.showToast({ title: xConfig.i18n.t("tmui4x.checkbox.tips"), icon: 'none', mask: true })
|
||||
|
||||
return;
|
||||
}
|
||||
oldvalueList.value.splice(index, 1, {
|
||||
id: nowitem.id,
|
||||
data: nowitem
|
||||
} as XCHECKBOX_LISTITEM_TYPE)
|
||||
|
||||
} else {
|
||||
oldvalueList.value.push({
|
||||
id: nowitem.id,
|
||||
data: nowitem
|
||||
} as XCHECKBOX_LISTITEM_TYPE)
|
||||
}
|
||||
|
||||
getcheckvaluelist()
|
||||
|
||||
if (ischange) {
|
||||
/**
|
||||
* 等同v-model=""
|
||||
*/
|
||||
emits("update:modelValue", checkvaluelist.value)
|
||||
/**
|
||||
* 选项变化时触发。
|
||||
* @param val {string[]} 当前选中的值
|
||||
*/
|
||||
emits("change", checkvaluelist.value)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 监听器
|
||||
watch((): Array<string|number|boolean> => props.modelValue, (newValue : Array<string|number|boolean>) => {
|
||||
let n = newValue.join("")
|
||||
let v = checkvaluelist.value.join("")
|
||||
if (n != v) {
|
||||
checkvaluelist.value = newValue
|
||||
setOldCheckboxValue();
|
||||
}
|
||||
},{deep:true})
|
||||
|
||||
// 生命周期
|
||||
onBeforeUnmount(() => {
|
||||
isDestroy.value = true;
|
||||
clearTimeout(tid.value)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
checkvaluelist.value = props.modelValue;
|
||||
isDestroy.value = false;
|
||||
})
|
||||
|
||||
// 提供响应式数据给子组件
|
||||
provide('xCheckboxModelvalue', computed((): Array<string|number|boolean> => checkvaluelist.value))
|
||||
|
||||
defineExpose({
|
||||
/** 添加多选项 **/
|
||||
addItem,
|
||||
/** 获取所有选中的值 **/
|
||||
getAllSelecteds: () => checkvaluelist.value
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<view class="xCheckboxGroup" :style="{'flex-direction':direction}">
|
||||
<!--
|
||||
@slot 从1.1.2开始允许是非直接x-checkbox子节点布局,但考虑到性能建议是直接子节点.
|
||||
-->
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
<style>
|
||||
.xCheckboxGroup {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user