Web Components 是前端开发中的一种新技术,它可以帮助开发者将页面模块化,并实现组件化的开发方式。在本文中,我们将介绍使用 Web Components 实现城市选择和省市区三级联动的技巧和代码示例。
城市选择组件
城市选择是一个常用的组件,它可以帮助用户快速选择自己所在的城市。使用 Web Components 可以将城市选择组件封装成一个独立的组件,方便在不同的项目中复用。
城市数据
城市选择组件的核心是城市数据。在本文中,我们将使用中国城市数据作为示例。我们可以将城市数据封装成一个 JSON 格式的文件,如下所示:
// javascriptcn.com 代码示例 [ { "province": "北京市", "cities": ["北京市"] }, { "province": "江苏省", "cities": ["南京市", "苏州市", "无锡市", "徐州市", "常州市", "连云港市", "淮安市", "盐城市", "扬州市", "镇江市", "泰州市", "宿迁市"] }, { "province": "广东省", "cities": ["广州市", "深圳市", "珠海市", "汕头市", "韶关市", "佛山市", "江门市", "湛江市", "茂名市", "肇庆市", "惠州市", "梅州市", "汕尾市", "河源市", "阳江市", "清远市", "东莞市", "中山市", "潮州市", "揭阳市", "云浮市"] }, { "province": "四川省", "cities": ["成都市", "自贡市", "攀枝花市", "泸州市", "德阳市", "绵阳市", "广元市", "遂宁市", "内江市", "乐山市", "南充市", "眉山市", "宜宾市", "广安市", "达州市", "雅安市", "巴中市", "资阳市", "阿坝藏族羌族自治州", "甘孜藏族自治州", "凉山彝族自治州"] } ]
城市选择组件实现
我们先来看一下城市选择组件的 HTML 结构:
<city-selector></city-selector>
城市选择组件中需要包含一个输入框和下拉框,用户可以在输入框中输入城市名称,下拉框会显示匹配的城市列表。用户选择一个城市后,输入框的值会更改为所选城市。
城市选择组件的 CSS 样式
在城市选择组件的 CSS 样式中,我们需要定义下拉框的样式和动画效果:
// javascriptcn.com 代码示例 .city-selector__dropdown { background-color: #fff; border: 1px solid #ddd; border-radius: 4px; box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.2); overflow-y: auto; max-height: 200px; position: absolute; top: 36px; left: 0; right: 0; padding: 0; margin: 0; z-index: 1; opacity: 0; transition: all 0.3s ease-in-out; transform: scale(0.8); transform-origin: center top; padding: 8px 0px; text-align: left; } .city-selector__dropdown--show { opacity: 1; transform: scale(1); }
城市选择组件的 JS 代码实现
在城市选择组件的 JS 代码中,我们需要实现以下功能:
- 获取城市数据;
- 监听输入框的输入事件,根据输入内容筛选城市数据,然后显示下拉框;
- 监听下拉框中每个城市的点击事件,然后将选中的城市填充到输入框中。
// javascriptcn.com 代码示例 class CitySelector extends HTMLElement { constructor() { super(); this.provinces = []; this.cities = []; this._shadowRoot = this.attachShadow({ mode: "open" }); this._shadowRoot.innerHTML = ` <style> .city-selector__input { padding: 8px; border: 1px solid #ddd; border-radius: 4px; width: 100%; box-sizing: border-box; } .city-selector__dropdown { background-color: #fff; border: 1px solid #ddd; border-radius: 4px; box-shadow: 0px 1px 5px rgba(0, 0, 0, 0.2); overflow-y: auto; max-height: 200px; position: absolute; top: 36px; left: 0; right: 0; padding: 0; margin: 0; z-index: 1; opacity: 0; transition: all 0.3s ease-in-out; transform: scale(0.8); transform-origin: center top; padding: 8px 0px; text-align: left; } .city-selector__dropdown--show { opacity: 1; transform: scale(1); } </style> <div class="city-selector"> <input class="city-selector__input" type="text" placeholder="请输入城市"> <ul class="city-selector__dropdown"></ul> </div> `; } connectedCallback() { fetch("cities.json") .then((response) => response.json()) .then((json) => { this.provinces = json; }); const input = this._shadowRoot.querySelector(".city-selector__input"); const dropdown = this._shadowRoot.querySelector(".city-selector__dropdown"); const cityList = this._shadowRoot.querySelector(".city-selector__dropdown"); input.addEventListener("input", (e) => { const value = e.target.value.trim(); if (value === "") { dropdown.classList.remove("city-selector__dropdown--show"); return; } let cities = []; this.provinces.forEach((province) => { cities = cities.concat( province.cities.filter((city) => city.toLowerCase().startsWith(value.toLowerCase()) ) ); }); if (cities.length === 0) { dropdown.classList.remove("city-selector__dropdown--show"); return; } cityList.innerHTML = ""; for (let city of cities) { const cityItem = document.createElement("li"); cityItem.innerText = city; cityItem.addEventListener("click", (e) => { input.value = city; dropdown.classList.remove("city-selector__dropdown--show"); }); cityList.appendChild(cityItem); } dropdown.classList.add("city-selector__dropdown--show"); }); document.addEventListener("click", (e) => { if (!this.contains(e.target)) { dropdown.classList.remove("city-selector__dropdown--show"); } }); } } customElements.define("city-selector", CitySelector);
省市区三级联动组件
省市区三级联动是一个常用的组件。在本文中,我们将使用 Web Components 实现一个简单的省市区三级联动组件,并展示它的基本实现原理。
省市区数据
省市区三级联动组件的核心是省市区数据。在本文中,我们将使用中国省市区数据作为示例。我们可以将省市区数据封装成一个 JSON 格式的文件,如下所示:
// javascriptcn.com 代码示例 [ { "name": "北京市", "code": "110000", "children": [ { "name": "市辖区", "code": "110100", "children": [] } ] }, { "name": "江苏省", "code": "320000", "children": [ { "name": "南京市", "code": "320100", "children": [ { "name": "玄武区", "code": "320102" }, { "name": "秦淮区", "code": "320104" }, { "name": "建邺区", "code": "320105" }, { "name": "鼓楼区", "code": "320106" }, { "name": "浦口区", "code": "320111" }, { "name": "栖霞区", "code": "320113" }, { "name": "雨花台区", "code": "320114" }, { "name": "江宁区", "code": "320115" }, { "name": "六合区", "code": "320116" }, { "name": "溧水区", "code": "320117" }, { "name": "高淳区", "code": "320118" } ] } ] }, { "name": "广东省", "code": "440000", "children": [ { "name": "广州市", "code": "440100", "children": [ { "name": "荔湾区", "code": "440103" }, { "name": "越秀区", "code": "440104" }, { "name": "海珠区", "code": "440105" }, { "name": "天河区", "code": "440106" }, { "name": "白云区", "code": "440111" }, { "name": "黄埔区", "code": "440112" }, { "name": "番禺区", "code": "440113" }, { "name": "花都区", "code": "440114" }, { "name": "南沙区", "code": "440115" }, { "name": "从化区", "code": "440117" }, { "name": "增城区", "code": "440118" } ] } ] }, { "name": "四川省", "code": "510000", "children": [ { "name": "成都市", "code": "510100", "children": [ { "name": "锦江区", "code": "510104" }, { "name": "青羊区", "code": "510105" }, { "name": "金牛区", "code": "510106" }, { "name": "武侯区", "code": "510107" }, { "name": "成华区", "code": "510108" }, { "name": "龙泉驿区", "code": "510112" }, { "name": "青白江区", "code": "510113" }, { "name": "新都区", "code": "510114" }, { "name": "温江区", "code": "510115" }, { "name": "双流区", "code": "510116" }, { "name": "郫都区", "code": "510117" }, { "name": "金堂县", "code": "510121" }, { "name": "大邑县", "code": "510129" }, { "name": "蒲江县", "code": "510131" }, { "name": "新津县", "code": "510132" }, { "name": "都江堰市", "code": "510181" }, { "name": "彭州市", "code": "510182" }, { "name": "邛崃市", "code": "510183" }, { "name": "崇州市", "code": "510184" } ] } ] } ]
省市区三级联动组件实现
在省市区三级联动组件的实现中,我们需要使用三个 select 元素来实现省市区联动功能。当用户选择省份时,该省份下属的市级地区会显示在 city-select 元素中。当用户选择市级地区时,该市级地区下属的区县会显示在 district-select 元素中。
以下是省市区三级联动组件的 HTML 结构:
<area-selector></area-selector>
在省市区三级联动组件的 JS 代码中,我们需要实现以下功能:
- 获取省市区数据;
- 监听省份选项的改变,根据省份选项的值渲染对应的市级地区选项;
- 监听市级地区选项的改变,根据市级地区选项的值渲染对应的区县选项。
// javascriptcn.com 代码示例 class AreaSelector extends HTMLElement { constructor() { super(); this._shadowRoot = this.attachShadow({ mode: "open" }); this._shadowRoot.innerHTML = ` <style> select { padding: 8px; border: 1px solid #ddd; border-radius: 4px; margin-right: 8px; box-sizing: border-box; } </style> <div class="area-selector"> <select class="province-select"></select> <select class="city-select"></select> <select class="district-select"></select> </div> `; } connectedCallback() { fetch("areas.json") .then((response) => response.json()) .then((json) => { this.provinces = json; const provinceSelect = this._shadowRoot.querySelector(".province-select"); const citySelect = this._shadowRoot.querySelector(".city-select"); const districtSelect = this._shadowRoot.querySelector(".district-select"); this.renderProvinceSelect(provinceSelect); provinceSelect.addEventListener("change", (e) => { this.renderCitySelect(citySelect, e.target.value); districtSelect.innerHTML = ""; }); citySelect.addEventListener("change", (e) => { this.renderDistrictSelect(districtSelect, provinceSelect.value, e.target.value); }); }); } renderProvinceSelect(selectElement) { const fragment = document.createDocumentFragment(); for (let province of this.provinces) { const option = document.createElement("option"); option.value = province.code; option.textContent = province.name; fragment.appendChild(option); } selectElement.appendChild(fragment); } renderCitySelect(selectElement, provinceCode) { const province = this.provinces.find((p) => p.code === provinceCode); selectElement.innerHTML = ""; const fragment = document.createDocumentFragment(); for (let city of province.children) { const option = document.createElement("option"); option.value = city.code; option.textContent = city.name; fragment.appendChild(option); } selectElement.appendChild(fragment); } renderDistrictSelect(selectElement, provinceCode, cityCode) { const province = this.provinces.find((p) => p.code === provinceCode); const city = province.children.find((c) => c.code === cityCode); selectElement.innerHTML = ""; const fragment = document.createDocumentFragment(); for (let district of city.children) { const option = document.createElement("option"); option.value = district.code; option.textContent = district.name; fragment.appendChild(option); } selectElement.appendChild(fragment); } } customElements.define("area-selector", AreaSelector);
总结
通过使用 Web Components 实现城市选择、省市区三级联动组件的学习,我们可以掌握 Web Components 的基本使用方法,并学习组件化开发的思想。Web Components 使得前端开发更加模块化、可复用,可以提高开发效率,减少代码维护成本,是一种非常值得学习的技术。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/65863155d2f5e1655d097087