望城区建设局网站,天津机械网站建设模板,没有备案的网站可以用ip访问吗,wordpress模板字体修改uniapp下拉选择组件 背景实现思路代码实现配置项使用尾巴 背景
最近遇到一个这样的需求#xff0c;在输入框中输入关键字#xff0c;通过接口查询到结果之后#xff0c;以下拉框列表形式展现供用户选择。查询了下uni-app官网和项目中使用的uv-ui库#xff0c;没找到符合条… uniapp下拉选择组件 背景实现思路代码实现配置项使用尾巴 背景
最近遇到一个这样的需求在输入框中输入关键字通过接口查询到结果之后以下拉框列表形式展现供用户选择。查询了下uni-app官网和项目中使用的uv-ui库没找到符合条件的组件。唯一一个有点类似的就是uni官方下拉框组件但是不支持input组件所以我们自己来实现一个。
我们先上一张图镇楼提供了多种模式和使用场景的情况
实现思路
那么实现这样一个组件要有哪些注意点了我大概罗列了一下 1、下拉框默认是不显示的要知道是在哪个位置显示 2、初始显示的组件不能定死可以是button可以是view或者是input要灵活 3、提供丰富的自定义配置 要解决第一和第二个问题我们的自定义组件需要使用插槽插槽用来放我们的初始显示组件来灵活适配各种组件。然后在插槽下面来通过绝对定位来显示下拉框组件默认隐藏然后暴露出显示函数给外部。
代码实现
接下来就是代码实现环节了有了思路直接按思路撸代码就行。 知道你们不喜欢啰嗦BB哈哈直接上代码 down-select.vue组件代码
templateview classlayout-columnview idparent stylewidth:fit-content;slot/slot/viewview:stylewidth:slotW;max-height: getListContentHeirpx;z-index: 9999;position: absolute;margin-top:slotH;(isShow ? : display:none;):class(dataList.length 0 ? data-box-shadow : data-box ) animateblock v-ifdataList.length 0view classdata-box-scroll:styleheight:dataList.length*(itemHeight-1)rpx;max-height: max*(itemHeight-1)rpx;text v-for(item,index) in dataList :keyitem[identifier]:classlayout-row less-center list-item (item.enable false ? : active):stylecolor:(item.enable false ? #dedede : (checkedIndex.indexOf(index) 0 ? itemSelectColor : itemColor));font-size:itemFontsizerpx;clickhandleListItem(index, item){{item[showKey]}}/text/viewview classlayout-row opera-btns less-center v-ifmode multipleview classopera-cancel layout-row center clickhandelCancel取消/viewview classopera-sure layout-row center clickhandelSure确定/view/view/blockview v-else :stylewidth:slotW; classstatus-text暂无数据/view/viewview classmask v-showisShow clickhandelCancel/view/view
/templatescriptexport default {name: down-select,props: {//要显示的字段showKey: {type: String,default: ,},mode: {type: String,default: single, //multiple// default: multiple},dataList: {type: Array,default: []},//选中的列表用作显示列表是展示已选中项checkedDataList: {type: Array,default: []},//最多展示几项后开始滑动max: {type: Number,default: 4},//数据项每个item高度rpxitemHeight: {type: Number,default: 80},//唯一标识符字段用来比对选中项和维持v-for列表中的key,不填此项无选中效果identifier: {type: String,default: },itemSelectColor: {type: String,default: #00aaff},itemColor: {type: String,default: black},itemFontsize: {type: Number,default: 30}},computed: {getListContentHei() {let len this.dataList.lengthlet signleH len this.max ? this.itemHeight * len : this.itemHeight * this.maxif (this.mode single) {return len 0 ? this.itemHeight : signleH} else {return len 0 ? this.itemHeight : (signleH this.itemHeight)}}},watch: {dataList: {handler: function(newVal, oldVal) {if (this.checkedDataList.length 0 this.identifier) {this.checkedIndex []this.checkedDataList.forEach(ele {let index newVal.findIndex(ele1 ele[this.identifier] ele1[this.identifier])if (index 0) {this.checkedIndex.push(index)}})}},immediate: true, // 组件创建时立即触发deep: true // 对象内部属性变化时也触发},checkedDataList: {handler: function(newVal, oldVal) {if (newVal.length 0 this.identifier) {this.checkedIndex []newVal.forEach(ele {let index this.dataList.findIndex(ele1 ele[this.identifier] ele1[this.identifier])if (index 0) {this.checkedIndex.push(index)}})}},immediate: true, // 组件创建时立即触发deep: true // 对象内部属性变化时也触发}},mounted() {this.$nextTick(() {uni.createSelectorQuery().in(this).select(#parent).boundingClientRect(res {if (res.width) {this.slotW ${res.width}pxthis.slotH ${res.height5}px}}).exec()})},data() {return {slotW: 0px,slotH: 0px,isShow: false,checkedIndex: [],animate: ,//传进来选中项后又改成未选中并确认多选模式生效checkedDels: []};},methods: {open() {if (this.checkedDataList.length 0 this.identifier) {this.checkedIndex []this.checkedDataList.forEach(ele {let index this.dataList.findIndex(ele1 ele[this.identifier] ele1[this.identifier])if (index 0) {this.checkedIndex.push(index)}})}this.isShow truethis.animate show-animate},close() {this.animate hide-animatethis.checkedIndex []this.checkedDels []this.isShow false},handleListItem(index, obj) {if(obj.enable false){return}if (this.mode single) {this.checkedIndex []this.checkedIndex.push(index)this.handelSure()} else {let sindex this.checkedIndex.indexOf(index)if (sindex 0) {if (this.identifier) {//判断未选中的项在传进来的已选项中是否存在let contain this.checkedDataList.filter(ele ele[this.identifier] this.dataList[index][this.identifier])if (contain.length 0) {//传进来的已选项中是否存在选择为未选中的内容let contain1 this.checkedDels.filter(ele ele[this.identifier] contain[0][this.identifier])if (contain1.length 0) {this.checkedDels.push(contain[0])}}}this.checkedIndex.splice(sindex, 1);} else {if (this.identifier) {let contain2 this.checkedDels.filter(ele ele[this.identifier] this.dataList[index][this.identifier])if (contain2.length 0) {let tempIndex this.checkedDels.findIndex(ele ele[this.identifier] this.dataList[index][this.identifier])if (tempIndex 0) {this.checkedDels.splice(tempIndex, 1)}}}this.checkedIndex.push(index)}}},handelCancel() {this.close()this.$emit(cancelDimss, )},handelSure() {let results []if (this.checkedIndex.length 0) {uni.showToast({title: 请选择至少一项,icon: none});return}this.checkedIndex.forEach(ele {if (this.dataList[ele]) {results.push(this.dataList[ele])}})//将本次选中结果清除this.checkedIndex []this.$emit(resultBack, results, this.checkedDels)this.close()}}}
/scriptstyle scoped.active {}.active:active {opacity: 0.6;}.layout-row {display: flex;flex-direction: row;}.layout-column {display: flex;flex-direction: column;}/* 整体方向居中 */.center {align-items: center;justify-content: center;}/* 主轴方向居中 */.main-center {justify-content: center;}/* 侧轴方向居中 */.less-center {align-items: center;}.data-box-scroll {width: 100%;overflow-y: scroll;}.data-box-scroll::-webkit-scrollbar {display: none}.data-box {background: white;border-radius: 8rpx;box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);z-index: 9999;}.data-box-shadow {background: white;border-radius: 8rpx;box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);z-index: 9999;}.list-item {width: 100%;height: 80rpx;margin-left: 20rpx;margin-right: 20rpx;border-bottom: 1rpx solid #D8DFEC;text-align: right;}.opera-btns {width: 100%;height: 80rpx;justify-content: flex-end;}.opera-cancel {width: 100rpx;height: 50rpx;background-color: white;box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);border-radius: 5rpx;font-size: 26rpx;}.opera-sure {width: 100rpx;height: 50rpx;background-color: #58a2e4;box-shadow: 0px 0px 3px 1px rgba(0, 0, 0, 0.1);border-radius: 5rpx;font-size: 26rpx;color: white;margin-right: 30rpx;margin-left: 30rpx;}.status-text {text-align: center;font-size: 28rpx;font-weight: 600;color: #c2c2c2;padding-top: 20rpx;padding-bottom: 20rpx;}.mask {position: fixed;background: transparent;top: 0;left: 0;width: 100%;height: 100%;z-index: 1;}.show-animate {animation-name: open;animation-duration: 1s;animation-iteration-count: 1;}keyframes open {0% {height: 0rpx;}100% {height: 100%;}}.hide-animate {animation-name: close;animation-duration: 1s;animation-iteration-count: 1;animation-fill-mode: forwards;}keyframes close {0% {height: 100%;}100% {height: 0rpx;}}
/styletest.vue测试页面代码
templateview classcontentdownSelect refselectRef showKeyname modesingle :dataListlist resultBackresultview classselect-btn clickhandleClick单选默认配置/view/downSelectview{{select.name}}/viewdownSelect refselectRef1 showKeyname modesingle itemColorred :dataListlist1 resultBackresult1view classselect-btn1 clickhandleClick1单选字体设置是否可点击/view/downSelectview{{select1.name}}/viewdownSelect refselectRef2 showKeyname modemultiple identifierid :dataListlist2:max5 :itemFontsize20 :checkedDataListselect2 resultBackresult2view classselect-btn2 clickhandleClick2多选字体大小设置超出设置项后滑动设置/view/downSelectview v-foritem in select2{{item.name}}/viewdownSelect refselectRef3 showKeyname modesingleview classselect-btn2 clickhandleClick3空数据/view/downSelectdownSelect refselectRef4 showKeyname modesingle :dataListlist4 resultBackresult4input classselect-btn1 placeholder请输入 inputhandleInput//downSelectview{{select4.name}}/view/view/templatescriptimport downSelect from /components/down-select.vueexport default {components: {downSelect},data() {return {select: {},select1: {},select2: [],select4: {},list: [{name: 选项一}, {name: 选项二}],list1: [{name: 选项一,enable: false}, {name: 选项二}, {name: 选项三}, {name: 选项四}, {name: 选项五}],list2: [{id: 0,name: 选项一}, {id: 1,name: 选项二}, {id: 2,name: 选项三}, {id: 3,name: 选项四}, {id: 4,name: 选项五}, {id: 5,name: 选项六}],list4: []}},onLoad() {},methods: {handleInput(e){this.$refs.selectRef4.open()//这里模拟接口访问获取数据setTimeout(() {this.list4 [{name: 选项一}, {name: 选项二}]},2000)},result(result) {this.select result[0]},result1(result){this.select1 result[0]},result2(result, dels []){// this.select2 resultif(this.select2.length 0){this.select2.push(...result)}else {result.forEach(ele {let contain this.select2.filter(ele1 ele.id ele1.id)if(contain.length 0){this.select2.push(ele)}})}if(dels.length 0){dels.forEach(ele {let index this.select2.findIndex(ele1 ele1.id ele.id)if(index 0){this.select2.splice(index, 1)}})}},result4(result){this.select4 result[0]},handleClick(){this.$refs.selectRef.open()},handleClick1() {this.$refs.selectRef1.open()},handleClick2 () {this.$refs.selectRef2.open()},handleClick3 () {this.$refs.selectRef3.open()}},}
/scriptstyle.content {width: 690rpx;margin: 25rpx;}.select-btn {width: 690rpx;height: 60rpx;display: flex;flex-direction: row;align-items: center;justify-content: center;border: 1rpx solid #e5e5e5;border-radius: 15rpx;}.select-btn1 {width: 490rpx;height: 60rpx;display: flex;margin-top: 100rpx;flex-direction: row;align-items: center;justify-content: center;border: 1rpx solid #e5e5e5;border-radius: 15rpx;}.select-btn2 {width: 690rpx;height: 60rpx;display: flex;margin-top: 100rpx;flex-direction: row;align-items: center;justify-content: center;border: 1rpx solid #e5e5e5;border-radius: 15rpx;}
/style以上代码都可以直接拷贝使用无其他关联项vue2、vue3、小程序、h5、APP都可用。
配置项
1、showKey传进来的数组单个对象在下拉框中要展示的值比如传的dataList为[{name: ‘韩梅梅’}],那showKey传name就行。 2、mode下拉框是单选还是多选模式见镇楼效果图。 3、dataList传入的数据列表列表为对象多选时对象需要指定唯一标识。 4、checkedDataList多选选中的列表数据。 5、max多条数据时最多显示几项后可以滑动。 6、identifier唯一标识符用作列表key和多选模式显示已选数据项时的标识。 7、itemSelectColor多选模式选中后的字体颜色。 8、itemColor字体颜色。 9、itemFontsize字体大小。
以上配置项在代码层面没做严格限制不同模式混用可能会有bug如果发现可以留言。配置项不满足你需求可以自行增删。
使用
页面引入down-select.vue然后参考第二节代码实现中的demo。
尾巴
今天的文章就到这里了希望能给大家帮助如果喜欢我的文章欢迎给我点赞评论关注谢谢大家