使用原生JavaScript实现部分表单元素

本文详细介绍了如何使用HTML、CSS和JavaScript实现下拉单选框和树形下拉菜单的效果,包括自定义样式和交互逻辑,以及通过DOM操作动态渲染选项。
摘要由CSDN通过智能技术生成

1.实现下拉单选框

实现效果如下:
在这里插入图片描述
实现代码如下:

<!DOCTYPE html>
<html lang="zh">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		.test {
			width: 300px;
			height: 50px;
			margin: 20px;
		}

		/* 自定义组件 */
		.custom-select-container {
			width: 100%;
			height: 100%;
			font-size: inherit;
			position: relative;
		}

		.custom-select-container .custom-select-content {
			cursor: pointer;
			box-sizing: border-box;
			padding-left: 5%;
			width: 100%;
			height: 100%;
			display: flex;
			align-items: center;
		}

		.custom-select-container .custom-select-pop-up-box {
			display: none;
			width: 100%;
			height: 100%;
		}

		.custom-select-container .custom-select-pop-up-box ul {
			margin: 0;
			padding: 0;
			width: 100%;
			height: 100%;
		}

		.custom-select-container .custom-select-pop-up-box li {
			cursor: pointer;
			list-style: none;
			box-sizing: border-box;
			padding-left: 5%;
			width: 100%;
			height: 100%;
			display: flex;
			align-items: center;
			/* background-color: yellow; */
		}

		.custom-select-container .custom-select-pop-up-box li:hover {
			background-color: rgb(1, 122, 253);
		}

		.custom-select-container .custom-select-down-arrow {
			width: 10%;
			position: absolute;
			right: 5%;
			top: 50%;
			transform: translateY(-50%);
		}

		.custom-select-container .custom-select-border {
			position: absolute;
			left: 0;
			top: 0;
			z-index: -1;
			width: 100%;
			height: 100%;
			border: 0.05rem solid rgb(1, 122, 253);
			border-radius: 0.3rem;
			box-sizing: border-box;
			background-color: #fff;
		}
	</style>
</head>

<body>
	<div style="position: relative;" class="container">
		<div class="test">
			<div class="custom-select-container" style="z-index: 10;">
				<div class="custom-select-content">请选择地区</div>
				<div class="custom-select-pop-up-box"></div>
				<img src="./img/down-arrow.png" alt="箭头" class="custom-select-down-arrow" />
				<div class="custom-select-border"></div>
			</div>
		</div>
		<div class="test">
			<div class="custom-select-container" style="z-index: 9;">
				<div class="custom-select-content">请选择位置</div>
				<div class="custom-select-pop-up-box"></div>
				<img src="./img/down-arrow.png" alt="箭头" class="custom-select-down-arrow" />
				<div class="custom-select-border"></div>
			</div>
		</div>
	</div>

	<script>
		function renderCustomSelect(data = [], selectIndex = 0, label = 'name', value = 'value') {
			const customSelectContentObj = document.querySelectorAll('.custom-select-container .custom-select-content')[
				selectIndex];
			const customSelectPopUpBoxObj = document.querySelectorAll('.custom-select-container .custom-select-pop-up-box')[
				selectIndex];
			const customSelectDownArrowObj = document.querySelectorAll('.custom-select-container .custom-select-down-arrow')[
				selectIndex];
			const customSelectBorderObj = document.querySelectorAll('.custom-select-container .custom-select-border')[
				selectIndex];
			const ulObj = document.createElement('ul');

			customSelectPopUpBoxObj.appendChild(ulObj);
			for (let i = 0; i < data.length; i++) {
				let liObj = document.createElement('li');
				liObj.setAttribute('data-value', data[i][value]);
				liObj.innerText = data[i][label];
				ulObj.appendChild(liObj);
			}

			customSelectDownArrowObj.onclick = function () {
				console.log(customSelectPopUpBoxObj.style.display);
				if (customSelectPopUpBoxObj.style.display == 'none' || customSelectPopUpBoxObj.style.display == '') {
					customSelectPopUpBoxObj.style.display = 'block';
					customSelectBorderObj.style.height = `calc(100% * ${data.length + 1})`
					customSelectDownArrowObj.style.transform = 'translateY(-50%) rotate(180deg)'
				} else {
					customSelectPopUpBoxObj.style.display = 'none';
					customSelectBorderObj.style.height = '100%'
					customSelectDownArrowObj.style.transform = 'translateY(-50%) rotate(0deg)'
				}
			}

			customSelectContentObj.onclick = function () {
				if (customSelectPopUpBoxObj.style.display == 'none' || customSelectPopUpBoxObj.style.display == '') {
					customSelectPopUpBoxObj.style.display = 'block';
					customSelectBorderObj.style.height = `calc(100% * ${data.length + 1})`
					customSelectDownArrowObj.style.transform = 'translateY(-50%) rotate(180deg)'
				} else {
					customSelectPopUpBoxObj.style.display = 'none';
					customSelectBorderObj.style.height = '100%'
					customSelectDownArrowObj.style.transform = 'translateY(-50%) rotate(0deg)'
				}
			}

			let list = customSelectPopUpBoxObj.getElementsByTagName('li');
			for (let i = 0; i < list.length; i++) {
				list[i].onclick = function () {
					console.log(this.innerText, this.getAttribute('data-value'));
					customSelectContentObj.innerText = this.innerText;
					customSelectPopUpBoxObj.style.display = 'none';
					customSelectBorderObj.style.height = '100%';
					customSelectDownArrowObj.style.transform = 'translateY(-50%) rotate(0deg)'
				}
			}
		}

		renderCustomSelect([{
			name: '北京-1',
			value: '1'
		}, {
			name: '上海-2',
			value: '2'
		}, {
			name: '广州-3',
			value: '3'
		}, {
			name: '深圳-4',
			value: '4'
		}], 0)

		renderCustomSelect([{
			name: '上单-1',
			value: '1'
		}, {
			name: '中单-2',
			value: '2'
		}, {
			name: '打野-3',
			value: '3'
		}, {
			name: '射手-4',
			value: '4'
		}, {
			name: '辅助-5',
			value: '5'
		}], 1)
	</script>
</body>

</html>

2.实现树形下拉单选框

实现效果如下:
在这里插入图片描述

实现代码如下:

<!DOCTYPE html>
<html lang="zh">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<style>
		.test {
			width: 300px;
			height: 30px;
			margin: 20px;
		}

		/* 自定义组件 */
		.custom-tree-select-container {
			width: 100%;
			height: 100%;
			font-size: inherit;
			position: relative;
		}

		.custom-tree-select-container .custom-tree-select-content {
			cursor: pointer;
			box-sizing: border-box;
			padding-left: 5%;
			width: 100%;
			height: 100%;
			display: flex;
			align-items: center;
		}

		.custom-tree-select-container .custom-tree-select-pop-up-box {
			display: none;
			width: 100%;
			height: 100%;
		}

		.custom-tree-select-container .custom-tree-select-pop-up-box .children-container {
			padding-left: 5%;
		}

		.custom-tree-select-container .custom-tree-select-pop-up-box .children-title {
			border-radius: 0.3rem;
			cursor: pointer;
			overflow: hidden;
			text-overflow: ellipsis;
			white-space: nowrap;
		}

		.custom-tree-select-container .custom-tree-select-pop-up-box .children-title:hover {
			background-color: rgb(121, 182, 247);
		}

		.custom-tree-select-container .custom-tree-select-pop-up-box .children-title .children-title-down-arrow {
			width: 5%;
			padding: 0 5%;
			transform: rotate(270deg);
		}

		.custom-tree-select-container .custom-tree-select-pop-up-box .children-item {
			overflow: hidden;
		}

		.custom-tree-select-container .custom-tree-select-down-arrow {
			width: 5%;
			position: absolute;
			right: 5%;
			top: 50%;
			transform: translateY(-50%);
		}

		.custom-tree-select-container .custom-tree-select-border {
			position: absolute;
			left: 0;
			top: 0;
			z-index: -1;
			width: 100%;
			height: 100%;
			border: 0.05rem solid rgb(1, 122, 253);
			border-radius: 0.3rem;
			box-sizing: border-box;
			background-color: #fff;
		}
	</style>
</head>

<body>
	<div style="position: relative;" class="container">
		<div class="test">
			<div class="custom-tree-select-container" style="z-index: 10;">
				<div class="custom-tree-select-content">请选择地区</div>
				<div class="custom-tree-select-pop-up-box"></div>
				<img src="./img/down-arrow.png" alt="箭头" class="custom-tree-select-down-arrow" />
				<div class="custom-tree-select-border"></div>
			</div>
		</div>
	</div>

	<script>
		function renderCustomTreeSelect(data = [], selectIndex = 0, label = 'name', value = 'value', children = 'children',
			optionHeight = 30) {
			const customSelectContentObj = document.querySelectorAll(
				'.custom-tree-select-container .custom-tree-select-content')[
				selectIndex];
			const customSelectPopUpBoxObj = document.querySelectorAll(
				'.custom-tree-select-container .custom-tree-select-pop-up-box')[
				selectIndex];
			const customSelectDownArrowObj = document.querySelectorAll(
				'.custom-tree-select-container .custom-tree-select-down-arrow')[
				selectIndex];
			const customSelectBorderObj = document.querySelectorAll('.custom-tree-select-container .custom-tree-select-border')[
				selectIndex];

			// 渲染选项
			function addSelectOptionItem(root, arr) {
				const childrenContainerObj = document.createElement('div');
				childrenContainerObj.classList.add('children-container')
				root.appendChild(childrenContainerObj);
				for (let i = 0; i < arr.length; i++) {
					let childrenTitle = document.createElement('div');
					childrenTitle.style.height = optionHeight + 'px';
					childrenTitle.style.lineHeight = optionHeight + 'px';
					childrenTitle.style.paddingRight = '30px';
					childrenTitle.classList.add('children-title');
					childrenTitle.setAttribute('data-value', arr[i][value]);
					childrenTitle.innerText = arr[i][label];
					let childrenTitleDownArrow = document.createElement("img")
					childrenTitleDownArrow.src = './img/down-arrow.png';
					childrenTitleDownArrow.classList.add('children-title-down-arrow');
					let childrenItem = document.createElement('div');
					childrenItem.classList.add('children-item')
					childrenItem.appendChild(childrenTitle);
					childrenContainerObj.appendChild(childrenItem);
					if (arr[i][children] && arr[i][children].length !== 0) {
						childrenTitle.appendChild(childrenTitleDownArrow);
						childrenItem.style.height = optionHeight + 'px';
						childrenItem.classList.add('have-children');
						addSelectOptionItem(childrenItem, arr[i][children])
					} else { }
				}
			}
			addSelectOptionItem(customSelectPopUpBoxObj, data)

			// 点击选项,选择内容,子项展开关闭
			const childrenContainerObj = document.querySelectorAll('.custom-tree-select-container .children-container')[
				selectIndex];
			childrenContainerObj.style.maxHeight = '260px';
			childrenContainerObj.style.overflowY = 'auto';
			let list = customSelectPopUpBoxObj.querySelectorAll('.custom-tree-select-container .children-title');
			for (let i = 0; i < list.length; i++) {
				if (!list[i].parentElement.classList.contains('have-children')) {
					list[i].onclick = function (e) {
						console.log(this.innerText, this.getAttribute('data-value'));
						customSelectContentObj.innerText = this.innerText;
						customSelectPopUpBoxObj.style.display = 'none';
						customSelectBorderObj.style.height = '100%';
						customSelectDownArrowObj.style.transform = 'translateY(-50%) rotate(0deg)'
						e.stopPropagation();
					}
				} else {
					list[i].parentElement.onclick = function (e) {
						if (this.style.height === optionHeight + 'px') {
							this.style.height = 'auto';
							list[i]['children'][0].style.transform = 'rotate(360deg)'
							customSelectBorderObj.style.height = childrenContainerObj.clientHeight + optionHeight +
								'px';
							e.stopPropagation()
						} else {
							this.style.height = optionHeight + 'px';
							list[i]['children'][0].style.transform = 'rotate(270deg)';
							customSelectBorderObj.style.height = childrenContainerObj.clientHeight + optionHeight + 'px';
							e.stopPropagation()
						}
					}
				}
			}

			// 弹出选项框
			function optionBoxHandle() {
				console.log(customSelectPopUpBoxObj.style.display);
				if (customSelectPopUpBoxObj.style.display == 'none' || customSelectPopUpBoxObj.style.display == '') {
					customSelectPopUpBoxObj.style.display = 'block';
					customSelectBorderObj.style.height = childrenContainerObj.clientHeight + optionHeight + 'px';
					customSelectDownArrowObj.style.transform = 'translateY(-50%) rotate(180deg)'
				} else {
					customSelectPopUpBoxObj.style.display = 'none';
					customSelectBorderObj.style.height = '100%'
					customSelectDownArrowObj.style.transform = 'translateY(-50%) rotate(0deg)'
				}
			}
			customSelectDownArrowObj.onclick = optionBoxHandle;
			customSelectContentObj.onclick = optionBoxHandle;
		}

		renderCustomTreeSelect([
			{
				name: '亚洲-1',
				value: '1',
				children: [
					{
						name: '中国-1-1',
						value: '1-1',
						children: [
							{
								name: '北京-1-1-1',
								value: '1-1-1',
								children: [
									{
										name: '海淀-1-1-1-1',
										value: '1-1-1-1'
									},
									{
										name: '昌平-1-1-1-2',
										value: '1-1-1-2'
									}
								]
							},
							{
								name: '上海-1-1-2',
								value: '1-1-2',
								children: [
									{
										name: '徐汇-1-1-2-1',
										value: '1-1-2-1'
									},
									{
										name: '闵行-1-1-2-2',
										value: '1-1-2-2'
									}
								]
							}
						]
					},
					{
						name: '日本-1-2',
						value: '1-2'
					},
					{
						name: '韩国-1-3',
						value: '1-3'
					}
				]
			},
			{
				name: '欧洲-2',
				value: '2'
			},
			{
				name: '北美-3',
				value: '3',
				children: [
					{
						name: '美国-3-1',
						value: '3-1'
					}
				]
			}
		])
	</script>
</body>

</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值