【基于vue写的select下拉框】

一个基于vue写的select下拉框

<template>
	<div class="selectCompents">
		<div class="selectBox">
			<div class="inputBox" @mouseenter="enter" @mouseleave="leave" :class="borderFlag ? 'focus':''"
				@click="handle_showClick"
				:style="{backgroundColor:bgColor+'!important',border:border,color:color+'!important'}">
				<input ref="inpVal" id="select" class="selectText" readonly type="text" @blur.stop="bulrSelect"
					v-model="value" :placeholder="placeholder" />
					<!-- <div class="moreBox" style="width: 100%;height: 100px;position: absolute;top: 0;left: 0;background-color: aqua;z-index: 20000;"></div> -->
				<div v-show="clearFlag==false" :class="showSelect ? 'roateOne':'roateTwo'" class="iconBox icon-dwon">
					<iconSvg class="iconStyle" :name="downicon">
					</iconSvg>
				</div>
				<div @click.stop="handle_clear" v-show="clearFlag" class="iconBox ">
					<iconSvg class="iconStyle" :name="clearicon"></iconSvg>
				</div>
			</div>
			<transition name="select">
				<ul class="selectUl" v-show="showSelect" @mouseenter="enterOtions" @mouseleave="leaveOptions">
					<li class="selectLi" :class="item.activeClass" v-for="(item,index) in list" :key="item.value"
						@click.stop="choose(item,index)">
						<!-- <p class="iconfont icon-fuxuankuang1"></p> -->
						<iconSvg v-if="item.checked && chooseMore" :name="checkicon" class="iconStyle-Check"></iconSvg>
						<iconSvg v-if="!item.checked && chooseMore" :name="checkedicon" class="iconStyle-Check"></iconSvg>
						<input @focus="focusOption(index)" class="optionsText" type="text" readonly :value="item.text">
					</li>
				</ul>
			</transition>
		</div>

	</div>
</template>

<script>
	export default {
		name: 'HelloWorld',
		props: {
			list: {
				type:Array,
				default:[{
						text: '市直222',
						value: 0
					},
					{
						text: '蓬江区',
						value: 1
					},
					{
						text: '江海区',
						value: 2
					},
					{
						text: '新会区',
						value: 3
					},
					{
						text: '台山市',
						value: 8
					},
					{
						text: '开平市',
						value: 7
					},
					{
						text: '鹤山市',
						value: 6
					},
					{
						text: '恩平市',
						value: 5
					},
					{
						text: '广东省',
						value: 10
					},
					{
						text: '深圳市',
						value: 11
					},
					{
						text: '广州市',
						value: 12
					},
					{
						text: '珠海市',
						value: 13
					},
					{
						text: '中山市',
						value: 14
					},
				],
			},
			recevie: Function,
			bgColor: {
				type: String,
				default: ''
			},
			border: {
				type: String,
				default: ''
			},
			color: {
				type: String,
				default: 'black'
			},
			placeholder: {
				type: String,
				default: '请选择选项'
			},
			downicon: {
				type: String,
				default: 'icon-xialajiantouxiao'
			},
			clearicon:{
				type:String,
				default:'icon-close'
			},
			clear: {
				type: Boolean,
				default: false,
			},
			chooseMore: {
				type: Boolean,
				default: false
			},
			checkicon: {
				type: String,
				default: 'icon-fuxuankuang'
			},
			checkedicon:{
				type:String,
				default:'icon-fuxuankuang1'
			}
		},
		components: {},
		created() {
			if (this.chooseMore) {
				this.list.forEach((item) => {
					item.checked = false
					item.activeClass = ''
				})
			}

		},
		data() {
			return {
				value: '',
				inputValue: '',
				key: '',
				showSelect: false,
				borderFlag: null,
				selectFlag: false,
				clearFlag: false,
				clearImg: {
					path: require('./close.svg')
				},
				checked: false,
				checkedList: [],
			}
		},
		methods: {
			//选中事件
			choose(item, index) {
				this.$refs.inpVal.focus();
				if (this.chooseMore) {
					item.checked = !item.checked
					if (item.checked) {
						item.activeClass = 'active'
						this.checkedList.push(item)
					} else {
						item.activeClass = ''
						for(let i=0;i<this.checkedList.length;i++){
							if(this.checkedList[i].value==item.value){
								this.checkedList.splice(i, 1)
							}
						}
					}
					let value = []
					this.checkedList.forEach((item) => {
						value.push(item.text)
					})
					this.value = value
					this.$emit('change', this.checkedList)
				} else {
					this.key = index
					for (let i = 0; i < this.list.length; i++) {
						if (this.key == i) {
							this.list[i].activeClass = 'active'
						} else {
							this.list[i].activeClass = ''
						}
					}
					this.value = this.list[index].text
					this.showSelect = false
					let obj = item
					this.$emit('change', obj)
				}
				this.borderFlag = false
				// let more=document.getElementsByClassName('moreBox')
				// console.log(more[0].clientHeight)
			},
			//是否展示下拉框事件
			handle_showClick() {
				this.showSelect = !this.showSelect
				if (this.showSelect) {
					this.borderFlag = true
				} else {
					this.borderFlag = false
				}
			},
			focusSelect() {},
			focusOption() {},
			//失去焦点事件
			bulrSelect() {
				if (this.selectFlag) {
					this.showSelect = true
				} else {
					this.showSelect = false
				}
			},
			showFocus() {
			},
			//移入事件
			enterOtions() {
				this.selectFlag = true
			},
			//移入事件
			leaveOptions() {
				this.selectFlag = false
			},
			//移入事件
			enter() {
				this.borderFlag = true
				if (this.value != '' && this.showSelect == false && this.clear === true) {
					this.clearFlag = true
					console.log(this.clear)
				}
			},
			//移出事件
			leave() {
				if (this.showSelect) {
					this.borderFlag = true
				} else {
					this.borderFlag = false
				}
				this.clearFlag = false
			},
			//清除按钮
			handle_clear() {
				console.log('22222')
				this.list.forEach((item) => {
					item.checked = false
					item.activeClass = ''
				})
				this.value = ''
				if (this.chooseMore) {
					this.checkedList = []
				} else {
					this.key = ''
				}
				this.$emit('change', this.checkedList)
			},
			//多选事件
			handle_checked(index) {

				console.log(this.list)
			}
		}
	}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
//调用时候请在外层包裹一个div标签,然后组件会继承div标签的高度和宽度
修改样式请用样式穿透例如:字体大小
.home(父组件)::v-deep .selectText(子组件需要改变的样式的类名){
}
配置项:
1.clear(清除按钮,例如:clear="true")
2.bgColor(设置背景颜色,例如bgColor='red')
3.border(设置边框,例如border="1px solid black")
4.color(设置select框字体颜色,例如color="blue")
5.placeholder(设置默认显示语句,例如placeholder="xxxxxxxxxxx")
6.downicon,clearicon,checkicon,checkedicon(图标,如需更换图标请自行申请iconfot项目,然后把index.css里面的链接替换成你的链接)
7.recevie(可以接收一个从父组件传来的函数,并且可以调用:recevie="recevie")
8.chooseMore(设置是否开启多选的配置项,例如:chooseMore="true")
9.@change="xxx"(xxx是一个函数,接收select组件传递的值)
<style scoped lang="less">
	.selectCompents {
		height: 100%;

		ul,
		li {
			list-style: none;
			margin: 0;
			padding: 0;
		}

		.selectBox {
			width: 100%;
			height: 100%;

			.inputBox {
				// padding: 0 10px;
				background-color: white;
				cursor: pointer;
				display: flex;
				align-items: center;
				height: 100%;
				border: 1px solid rgb(220, 223, 230);
				border-radius: 3px;
				position: relative;
				z-index: 0;

				.selectText {
					padding: 0 0 0 10px;
					display: block;
					// height: 30px;
					height: 100%;
					cursor: pointer;
					outline: none;
					border: none;
					width: 100%;
					border-radius: 3px;
					z-index: 1000;
					background-color: transparent !important;
				}

				.icon-dwon {
					position: absolute;
					right: 0px;
					z-index: 1;
				}

				.iconBox {
					padding: 0 10px;
					height: 100%;
					display: flex;
					align-items: center;

					.iconStyle {
						cursor: pointer;
						color: rgb(196, 192, 204);
					}
				}

			}

			.focus {
				border: 1px solid rgb(196, 192, 204) !important;
			}

			.roateOne {
				transform: rotate(180deg);
				transition: .1s linear;
			}

			.roateTwo {
				transform: rotate(360deg);
				transition: .1s linear;
			}

			.select-enter,
			.select-leave-to {
				transform: scaleY(0);
			}

			.select-enter-to,
			.select-leave {
				transform: scaleY(1);
			}

			.selectUl::-webkit-scrollbar {
				display: none;
			}

			.selectUl {
				height: 200px;
				overflow-y: scroll;
				box-shadow: 0px 2px 2px 0px rgba(0, 0, 0, 0.1);
				transition: 0.1s linear;

				.selectLi {
					text-align: left;
					cursor: pointer;
					padding: 5px 8px;
					display: flex;
					align-items: center;

					.optionsText {
						border: none;
						background-color: transparent;
						width: 100%;
						cursor: pointer;
						outline: none;
						padding: 0;
						margin-left: 5px;
					}

					.iconStyle-Check {}
				}

				.selectLi:first-child {
					margin-top: 0;
				}

				.selectLi:hover {
					background-color: rgb(245, 247, 250);
				}

				.active {
					color: blue;
				}
			}
		}
	}
</style>

项目地址:https://gitee.com/a1065770310/select/settings#index

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Vue中,当使用v-model动态渲染select框时,可能会遇到下框显示为空白的问题。这是因为select标签必须要有一个值才能正常显示,而默认情况下v-model绑定的变量是没有值的。因此,需要给v-model绑定的变量赋一个初始值,例如将select的初始值设置为空字符串。\[2\] 另外,还有两种解决方法可以解决这个问题。第一种方法是使用Vue的$set方法来为动态新增的属性赋值。在change事件中,可以使用this.$set来为inquire对象的selectData属性赋值,这样可以实现select框选择后赋值成功并显示选中的值。\[3\] 第二种方法是使用forceUpdate方法来强制刷新render函数。如果下框的数据是从其他接口获取的,并且数据层次较深,render函数可能无法自动更新,需要手动强制刷新。在select的change事件中,可以加上this.$forceUpdate()来强制刷新,这样就可以解决选中值不显示的问题。需要注意的是,forceUpdate只会影响实例本身和插入插槽的子组件,而不是所有子组件。\[3\] 综上所述,解决Vue隐藏select框的问题可以通过给v-model绑定的变量赋初始值,使用$set方法为动态新增的属性赋值,或者使用forceUpdate方法强制刷新render函数。 #### 引用[.reference_title] - *1* *2* [(详解)Vue设置select框的默认选项(解决select空白的bug)](https://blog.csdn.net/Andye11/article/details/126933085)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [vue中el-select框 选择后赋值成功 但是下选框上不显示选中的值的解决办法](https://blog.csdn.net/weixin_44900104/article/details/126348729)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值