歡迎點(diǎn)擊領(lǐng)取 -《前端開(kāi)發(fā)面試題進(jìn)階秘籍》:前端登頂之巔-最全面的前端知識(shí)點(diǎn)梳理總結(jié)
技術(shù)框架公司的選型:uni-app + uni-ui + vue3 + vite4 + ts
需求分析:微信小程序-uni-ui內(nèi)容
1、創(chuàng)建一個(gè)自定義的下拉,支持多個(gè)內(nèi)容的同時(shí)多選
2、定義好出入?yún)?shù),支持回顯內(nèi)容等
3、綁定對(duì)應(yīng)的v-model數(shù)據(jù)響應(yīng)
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-638000.html
1、代碼信息
<template>
<view tabindex="1" ref="customSelectRef" class="uni-select" @click.stop="handleClickDiv">
<view>
<template v-if="modelLabel.length">
<span class="custom-tag" :key="index" v-for="(item, index) in modelLabel">
<span>{{ item }}</span>
</span>
</template>
<span class="custom-tag" v-if="modelLabel.length && checkList.length - maxLength > 0">
+ {{ checkList.length - maxLength }}
</span>
<span v-if="!modelLabel.length" class="cus_placeholder">{{ placeholder }}</span>
<img
class="icon-delete"
v-if="modelLabel.length"
@click.stop="handleRemove"
:src="'../../static/icons/delete.png'"
/>
</view>
<transition>
<view class="cus_select_background" ref="cusSelectDropdown" v-if="isShowDropdown" @click="handleMemory">
<view class="cus_tabs" :key="index" v-for="(item, index) in cusDataListChecked">
<template v-if="item.children">
<view class="cus_tabs_title">{{ item.text }}</view>
<view class="cus_tabs_body">
<uni-data-checkbox
mode="tag"
:multiple="multiple"
v-model="item.checkList"
:localdata="item.children"
@change="(val) => handleCheckedChange(val, item)"
></uni-data-checkbox>
</view>
</template>
</view>
</view>
</transition>
<view v-if="isShowDropdown" class="custom_mask"></view>
</view>
</template>
<script setup lang="ts">
import { watch } from "vue";
import { toRaw } from "vue";
import { ref, onMounted, nextTick, onBeforeMount } from "vue";
const props = withDefaults(
defineProps<{
dataSource: any;
modelValue?: any;
placeholder?: string;
multiple?: boolean;
maxLength?: number;
}>(),
{
multiple: true,
dataSource: [],
modelValue: [],
maxLength: 3,
placeholder: "請(qǐng)選擇",
}
);
const emit = defineEmits(["update:modelValue", 'change']);
const customSelectRef = ref();
const cusSelectDropdown = ref();
const modelLabel = ref<Record<string, any>[]>([]);
const checkList = ref<string[]>([]);
const cusDataListChecked = ref<Record<string, any>[]>([]);
const isShowDropdown = ref<boolean>(false);
const isShowDownMemory = ref<boolean>(false);
const handleClickDiv = () => {
isShowDropdown.value = isShowDownMemory.value ? true : !isShowDropdown.value;
isShowDownMemory.value = false;
};
const handleMemory = () => {
isShowDownMemory.value = true;
};
const handleCheckedChange = (e: Record<string, any>, row: Record<string, any>) => {
const { data } = e.detail;
row.checkLabel = data.map((opt) => opt.text);
getModelVal();
};
const getModelVal = () => {
const newValue = toRaw(cusDataListChecked.value);
const newLabel = newValue.map((item) => item.checkLabel);
const newModelVal = newValue.map((item) => item.checkList);
const deconstructLabel = newLabel?.flat();
const deconstructVal = newModelVal?.flat();
modelLabel.value = deconstructLabel.slice(0, props.maxLength);
checkList.value = deconstructVal;
emit("update:modelValue", newModelVal);
};
const handleRemove = (e) => {
modelLabel.value = [];
checkList.value = [];
if (isShowDropdown.value) {
isShowDropdown.value = false;
}
if (props.multiple) {
cusDataListChecked.value = addCheckProperties(props.dataSource);
}
emit("update:modelValue", []);
};
const addCheckProperties = (treeData) => {
let result = [];
result = JSON.parse(JSON.stringify(treeData));
result.forEach((node) => {
const child = node.children;
node.checkList = [];
node.checkLabel = [];
if (child && child.length > 0) {
addCheckProperties(child);
}
});
return result;
};
const findTreeChecked = (treeData) => {
const newLabel = [];
const val = toRaw(props.modelValue);
treeData.forEach((node, index) => {
if (node.children?.length) {
const child = node.children;
const bool = child.some((opt) => {
const isExist = val[index] && val[index].includes(opt.value);
isExist ? newLabel.push(opt.text) : void null;
return isExist;
});
if (bool) {
node.checkLabel = newLabel;
node.checkList = val[index];
}
}
});
return treeData;
};
watch(isShowDropdown, (newVal) => {
emit('change', newVal, props.modelValue)
})
onBeforeMount(() => {
if (props.multiple) {
cusDataListChecked.value = addCheckProperties(props.dataSource);
}
});
onMounted(async () => {
await nextTick();
if (props.multiple && props.modelValue.length) {
cusDataListChecked.value = findTreeChecked(cusDataListChecked.value);
getModelVal();
}
});
</script>
<style lang="scss" scoped>
.uni-select {
font-size: 14px;
border: 1px solid #e5e5e5;
box-sizing: border-box;
border-radius: 4px;
padding: 0 5px 0 10px;
position: relative;
display: flex;
user-select: none;
flex-direction: row;
align-items: center;
border-bottom: solid 1px #e5e5e5;
width: 100%;
flex: 1;
height: 35px;
position: relative;
}
.cus_placeholder {
color: #6a6a6a;
font-size: 12px;
}
.icon-delete {
position: absolute;
width: 18px;
height: 18px;
right: 5px;
margin-top: 3.5px;
z-index: 10;
}
.cus_select_background {
width: 95vw;
max-height: 260px;
box-sizing: border-box;
border-radius: 4px;
font-size: 13px;
color: #606266;
background: #ffffff;
border: 1px solid #e4e7ed;
position: absolute;
top: 40px;
left: 0px;
padding: 5px 8px;
z-index: 10;
}
.cus_tabs {
margin-bottom: 8px;
.cus_tabs_title {
font-weight: 600;
margin-bottom: 4px;
}
.cus_tabs_body {
margin-left: 12px;
}
}
.custom-tag {
color: #909399;
display: inline-flex;
justify-content: center;
align-items: center;
height: 24px;
padding: 0 9px;
line-height: 1;
border-radius: 4px;
white-space: nowrap;
font-size: 13px;
margin-right: 5px;
background-color: #f0f2f5;
}
.custom_mask {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 1;
display: flex;
justify-content: center;
align-items: center;
}
</style>
2、使用api介紹
1、樹(shù)形結(jié)構(gòu)入?yún)ⅲ?code>dataSource=[{ ext: "服務(wù)器狀態(tài)", children: [{ text: "在線", value: 0}]}],
2、標(biāo)簽引用:<ivuSelect :maxLength="2" ref="ivuSelectRef" v-model="customSelect" :dataSource="deviceDataList" style="width: 100%; margin-left: 5px" />
3、相關(guān)api說(shuō)明文檔在文章底部文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-638000.html
參數(shù) | 說(shuō)明 | 類型 | 默認(rèn)值 | 必填項(xiàng) |
---|---|---|---|---|
dataSource | [{}]-label,value;樹(shù)形結(jié)構(gòu) | Array[] | [] | 是 |
modelValue | 當(dāng)前選中項(xiàng)內(nèi)容 | Array | [] | 否 |
placeholder | 輸入框內(nèi)容 | String | 請(qǐng)輸入 | 否 |
multiple | 是否開(kāi)啟多選 | Boolean | false | 否 |
maxLength | 輸入框最大標(biāo)簽長(zhǎng)度 | Number | 3 | 否 |
到了這里,關(guān)于uni-app微信小程序開(kāi)發(fā)自定義select下拉多選內(nèi)容篇的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!