原生JS实现省市县筛选

52 阅读1分钟

效果

动画.gif

方法

  1. 两个步骤,初始化界面, 交互事件
  2. 将所有的样式写好,包括动画,后期添加类
  3. html 包含三个select,每个select展现不提供的数据
  4. 默认后面的div 是不可选中的
  5. 保存好上次的数据,传递下次使用

结构

image.png

初始化

初始化阶段,默认数据的填充,和每个状态的管理(是否可点击) 写好html,css 将数据填充到ProvinceDiv里面

	fillSelect(doms.selProvince, datas); // 接受两个参数,填充的div和数据
	fillSelect(doms.selCity, []);
	fillSelect(doms.selArea, []);
        // 如果没有填充的数据将状态设置为disabled
	function fillSelect(select, list) {
		select.className = `select ${list.length ? '' : 'disabled'}`;
		const tipName = select.dataset.name;
		const span = select.querySelector('span');
		span.innerText = '请选择' + tipName;
                // 精髓:解决数据传递问题
                // 将本次使用的数据保存,下次接着这个数据筛选
		select.datas = list;
		const ul = select.querySelector('ul');
		ul.innerHTML = list.map((e) => { return `<li>${ e.label}</li>`}).join("");
	}

交互事件

  1. 单击div事件,显示二级菜单
  2. 二级菜单选中toggle样式
  3. select绑定不同的渲染数据时间.
	regCommonEvent(doms.selProvince);
	regCommonEvent(doms.selCity);
	regCommonEvent(doms.selArea);
        // 注册三个公共事件
        // div都需要展开二级菜单,和菜单项
	function regCommonEvent(select) {
		const title = select.querySelector('.title');
		// title 点击事件
		title.addEventListener('click', () => {
			// 禁用状态下无法操作
			if (select.classList.contains('disabled')) {
				return;
			}
			const expands = select.querySelectorAll('.select.expand');
			for (const el of expands) {
				el.classList.remove('expand');
			}
			select.classList.toggle('expand');
		});
		const ul = select.querySelector('.options');
		// ul事件
		ul.addEventListener('click', (e) => {
			if (e.target.tagName !== 'LI') {
				return;
			}
			const beforeActiveLi = select.querySelector('li.active');
			beforeActiveLi && beforeActiveLi.classList.remove('active');
			const li = e.target;
			li.classList.add('active');
			const span = select.querySelector('span');
			span.innerText = e.target.innerText;
		});
                //鼠标移除隐藏二级菜单
		ul.addEventListener('mouseleave', () => {
			select.classList.remove('expand');
		});
	}

数据渲染

image.png

        //给省div绑定事件,将数据渲染到城市div
	function regProvinceEvent() {
		const ul = doms.selProvince.querySelector('.options');
		ul.addEventListener('click', (e) => {
			let li = e.target;
			if (li.tagName !== 'LI') {
				return
			}
			const pr = doms.selProvince.datas.find((e) => {
				return e.label === li.innerText;
			});
                        //渲染到城市
			fillSelect(doms.selCity, pr.children);
                        //将地区div,disabled
			fillSelect(doms.selArea, []);
		});
	}
        //给城市div绑定事件,将数据渲染到地区div
	function regCityEvent() {
		const ul = doms.selCity.querySelector('.options');
		ul.addEventListener('click', (e) => {
			let li = e.target;
			if (li.tagName !== 'LI') {
				return;
			}
			const pr = doms.selCity.datas.find((e) => {
				return e.label === li.innerText;
			});
                        //渲染到地区
			fillSelect(doms.selArea, pr.children);
		});
	}