アイデア: 各ドロップダウン メニューはコンポーネントとして、一連のデータを受け取り、さまざまなデータの内容に基づいてさまざまなメニュー オプションを生成できます。 3 つのレベル間の相関関係は、イベントのスローによって実現されます。データはバックグラウンドから取得されます。
省メニューをクリックして陝西省を選択すると、メニュー コンポーネントはイベントスローを通じて現在の省をスローします。州を知ると、その州内の都市データをバックグラウンドから取得できます。等々。 [関連する推奨事項:JavaScript ビデオ チュートリアル]
達成効果:
import Component from "./Component.js"; export default class DropDownMemu extends Component { _list; // 当前下拉菜单的可选项。 _name; // 当前选择显示的名字例如: "北京" label; // 当前下拉菜单的标签,province city county spanLabel; // 标签容器 spanCaret; // 三角形 ul; // 下拉选项容器 bool=false; // 控制鼠标事件,聚焦状态或正在选择时,不触发鼠标划入滑出效果。 // 根据不同的状态设置下拉菜单的样式。 static DROPDOWN = Symbol(); static DEFAULT = Symbol(); // 静态全局变量 每创建一个下拉菜单,都存储到这个对象中,全局管理创建的每一个下拉菜单。 static Obj = {}; constructor(_label) { super("p"); this.label = _label; // 创建HTML结构 this.render(); // 设置样式 this.setStyle(); // 鼠标滑入滑出点击,聚焦失焦,点击事件 this.elem.addEventListener("focusin", e =>this.mouseHandler(e)); this.elem.addEventListener("focusout", e =>this.mouseHandler(e)); this.elem.addEventListener("mouseenter", e=>this.mouseHandler(e)); this.elem.addEventListener("mouseleave", e=>this.mouseHandler(e)); this.elem.addEventListener("click", e => this.mouseHandler(e)); } mouseHandler(e){ switch(e.type){ case "mouseenter": if(this.bool) return this.elem.style.backgroundColor = "#e6e6e6"; break; case "mouseleave": if(this.bool) return this.elem.style.backgroundColor = "#fff"; break; case "focusin": this.setState(DropDownMemu.DROPDOWN); this.bool = true; break; case "focusout": this.setState(DropDownMemu.DEFAULT); this.bool = false; case "click" : if(e.target.constructor !== HTMLLIElement) return this._name = e.target.textContent; // 当点击时修改当前显示的内容,重设样式,并抛发事件告知外部当前的内容。 this.setContent(); let evt = new FocusEvent("focusout"); this.elem.dispatchEvent(evt); } } set name(_name){ this._name = _name; this.setContent(); } get name(){ return this._name; } set list(_list){ this._list = _list; this.ul.innerHTML = ""; this.ul.appendChild(this.createLi()); } // 修改菜单当前显示的内容并并抛发数据 setContent(_name){ this._name = _name || this._name; this.spanLabel.textContent = this._name; let evt = new MouseEvent("change"); if(!evt.data) evt.data = {} evt.data[this.label] = this._name; this.dispatchEvent(evt); } // 根据指定的list创建下拉菜单选项。 createLi(_list){ this._list = _list || this._list; let elem = document.createDocumentFragment(); this._list.forEach((item, index) => { let li = document.createElement("li"); li.textContent = item; Object.assign(li.style, { lineHeight:"26px", padding:"0 15px", }) elem.appendChild(li); }) return elem; } setState(type){ switch(type){ case DropDownMemu.DROPDOWN: this.elem.style.backgroundColor = "#e6e6e6"; this.ul.style.display = "block"; break; case DropDownMemu.DEFAULT: this.elem.style.backgroundColor = "#fff"; this.ul.style.display = "none"; break; } } appendTo(parent){ super.appendTo(parent); DropDownMemu.Obj[this.label] = this; } render() { this.elem.setAttribute("tabIndex",1); this.spanLabel = document.createElement("span"); this.spanCaret = document.createElement("span"); this.ul = document.createElement("ul"); this.elem.appendChild(this.ul); this.spanLabel.textContent = this._name; this.elem.appendChild(this.spanLabel); this.elem.appendChild(this.spanCaret); } setStyle() { Object.assign(this.elem.style, { float: "left", minHeight: "20px", minWidht: "80px", color: "#333", fontWeight: "normal", textAlign: "center", whiteSpace: "nowrap", verticalAlign: "middle", cursor: "pointer", border: "1px solid #ccc", borderRadius: "4px", backgroundColor: "#fff", padding: "6px 12px", fontSize: "14px", userSelect: "none", marginRight: "100px", position:"relative", }); Object.assign(this.spanLabel.style, { float: "left", padding: "0 5px" }) Object.assign(this.spanCaret.style, { display: "inline-block", verticalAlign: "middle", borderTop: "4px dashed", borderRight: "4px solid transparent", borderLeft: "4px solid transparent", }) Object.assign(this.ul.style, { listStyle: "none", position: "absolute", top: "100%", left: "0", zIndex: "1000", minWidth: "100px", padding: "5px 0px", margin: "2px 0 0", fontSize: "14px", textAlign: "left", backgroundColor: "#fff", border: "1px solid rgba(0, 0, 0, 0.15)", borderRadius: "4px", boxShadow: "0 6px 12px rgba(0, 0, 0, 0.175)", display: "none", }) } }
export default class Component extends EventTarget{ elem; constructor(_type){ super(); this.elem = this.createElem(_type); } createElem(_type){ let elem = document.createElement(_type); return elem; } appendTo(parent){ if(typeof parent==="string") parent = document.querySelector(parent); parent.appendChild(this.elem); } }
let http = require("http"); let querystring = require("querystring"); let data, req, res; // 读取所有城市数据并解析为对象,同步读取。 let fs = require("fs"); let allCityInfo = JSON.parse(fs.readFileSync('./city.json')); let server = http.createServer(listenerHandler); server.listen(4010,"10.9.72.245",listenerDoneHandler); function listenerHandler(_req,_res){ req = _req; res = _res; res.writeHead(200,{ "content-type":"text/html;charset=utf-8", "Access-Control-Allow-Origin":"*", "Access-Control-Allow-Headers":"*", }); data=""; req.on("data",function(_data){ data=_data; }) req.on("end",receiveHandler); } function receiveHandler(){ // console.log(allCityInfo); // 根据请求头的url解析接口类型 let type = req.url.trim().split("?")[0].replace(/\//g,""); console.log(type); // 根据请求头的url解析传入的参数 if(req.method.toUpperCase()==="GET"){ if(req.url.includes("favicon.ico")) return res.end(); else data = req.url.includes("?") ? req.url.split("?")[1] : ""; } try{ data = JSON.parse(data); }catch{ data = querystring.parse(data); } console.log(data); // 根据接口类型查找数据。 let list = {}; switch(type){ case "getProvince": list.province = Object.keys(allCityInfo); break; case "getCity" : list.city = Object.keys(allCityInfo[data.province]); break; case "getCounty": list.county = allCityInfo[data.province][data.city]; break; } console.log(list); res.write(JSON.stringify(list)); res.end() } function listenerDoneHandler(){ console.log("开启服务成功"); }
"北京": {
"北京": ["東城区"、"西城区"、"崇文区" 、「玄武区」、「朝陽区」、「豊台区」、「石景山区」、「海淀区」、「門頭溝区」、「房山区」、「通州区」、「順義区」、「昌平区」 "、"大興区"、"平谷区"、"懐柔区"、"密雲県"、"延慶県"、"その他"]
},
"天津": {
"天津": ["和平区"、"河東区"、"河西区"、"南海区"、"河北区"、"宏街区"、"浜海新区"、"東里区"、"西清区」、「晋南区」、「北城区」、「寧河区」、「武清区」、「静海県」、「保地区」、「吉県」、「塘沽区」、「漢谷区」、「」大崗区」、「保地区」、「その他」]
},
}
以上が3階層連携メニューをJSで実装する方法を詳しく解説した記事(アイデア解説付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。