您好,登錄后才能下訂單哦!
這篇“怎么使用JS實(shí)現(xiàn)三級(jí)聯(lián)動(dòng)菜單”文章的知識(shí)點(diǎn)大部分人都不太理解,所以小編給大家總結(jié)了以下內(nèi)容,內(nèi)容詳細(xì),步驟清晰,具有一定的借鑒價(jià)值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來(lái)看看這篇“怎么使用JS實(shí)現(xiàn)三級(jí)聯(lián)動(dòng)菜單”文章吧。
思路:每一個(gè)下拉菜單作為一個(gè)組件,可以接收一組數(shù)據(jù),根據(jù)數(shù)據(jù)內(nèi)容不同生成不同的菜單選項(xiàng)。三級(jí)之間的關(guān)聯(lián)通過(guò)事件拋發(fā)來(lái)實(shí)現(xiàn)。數(shù)據(jù)從后臺(tái)獲取。
當(dāng)點(diǎn)擊省份菜單選擇陜西時(shí),菜單組件會(huì)通過(guò)事件拋發(fā)把當(dāng)前的省份拋發(fā)出來(lái)。得知省份之后就可以從后臺(tái)獲取省份下面的城市數(shù)據(jù)。依次類推。
實(shí)現(xiàn)效果:
## URL:http://10.9.72.245:4010
## Method: "GET"
## 數(shù)據(jù)格式:
請(qǐng)求:QueryString
響應(yīng):JSON
1、http://10.9.72.245:4010/getProvince
2、http://10.9.72.245:4010/getCity
3、http://10.9.72.245:4010/getCounty
接口名:/getProvince
請(qǐng)求:無(wú)參數(shù)
響應(yīng):{"province":["北京","天津","河北",...]}
接口名:/getCity
請(qǐng)求:?province="河北"
響應(yīng):{"city":["石家莊", "唐山", "秦皇島",...]}
接口名:/getCounty
請(qǐng)求:?city="石家莊"
響應(yīng):{"county":["長(zhǎng)安區(qū)", "橋東區(qū)", "橋西區(qū)",...]}
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script type="module"> import QueryString from './js/QueryString.js'; import DropDownMemu from './js/DropDownMemu.js'; let cityInfo = {}; init(); function init(){ ajax("http://10.9.72.245:4010","getProvince").then(succeseFunction).catch(failFunction); } // ajax通信成功后執(zhí)行: function succeseFunction(_data){ let data = JSON.parse(_data); let key = Object.keys(data)[0]; data = Object.values(data)[0]; if(DropDownMemu.Obj[key]){ DropDownMemu.Obj[key].list = data; DropDownMemu.Obj[key].name = data[0]; }else{ let memu = new DropDownMemu(key); memu.addEventListener("change",changeHandler); memu.list = data; memu.name =data[0]; memu.appendTo("body"); cityInfo[key] = data[0]; } } // 當(dāng)菜單顯示內(nèi)容改變時(shí)接收到菜單拋發(fā)出的事件并獲取事件中攜帶的信息例如{"province":"陜西"}或者{"city":"西安"} function changeHandler(e){ let key = e.currentTarget.label; cityInfo[key] = e.data[key]; let interfaceName; if(e.data.province){ interfaceName = "getCity"; }else if(e.data.city){ interfaceName = "getCounty"; }else{ return } ajax("http://10.9.72.245:4010",interfaceName,cityInfo).then(succeseFunction).catch(failFunction); } /* ajax通信: 參數(shù)列表: url: 后臺(tái)服務(wù)地址 interfaceType:接口類型,如 "getProvince" data:傳輸?shù)臄?shù)據(jù),例如:{"province":"陜西"} 通信類型type:默認(rèn)"GET"請(qǐng)求 是否以json格式發(fā)送數(shù)據(jù):默認(rèn)為false */ function ajax(url,interfaceType,data,type="get",json=false){ type = type.toUpperCase(); let o = type==="GET"? null : data; if(data) data = json? JSON.stringify(data) : QueryString.stringify(data); else data = ""; return new Promise(function(resolve,reject){ let xhr = new XMLHttpRequest(); xhr.open(type,url + "/" + interfaceType + (type==="GET"? "?"+data : "")); xhr.send(o); xhr.onreadystatechange = function(){ if(xhr.readyState===4 && xhr.status===200){ resolve(xhr.response); }else if(xhr.readyState===4){ resolve(xhr.status); } } xhr.onerror= function(){ reject(xhr.response); } }) } // ajax通信失敗時(shí)執(zhí)行 function failFunction(_err){ console.log(_err); } </script> </body> </html>
import Component from "./Component.js"; export default class DropDownMemu extends Component { _list; // 當(dāng)前下拉菜單的可選項(xiàng)。 _name; // 當(dāng)前選擇顯示的名字例如: "北京" label; // 當(dāng)前下拉菜單的標(biāo)簽,province city county spanLabel; // 標(biāo)簽容器 spanCaret; // 三角形 ul; // 下拉選項(xiàng)容器 bool=false; // 控制鼠標(biāo)事件,聚焦?fàn)顟B(tài)或正在選擇時(shí),不觸發(fā)鼠標(biāo)劃入滑出效果。 // 根據(jù)不同的狀態(tài)設(shè)置下拉菜單的樣式。 static DROPDOWN = Symbol(); static DEFAULT = Symbol(); // 靜態(tài)全局變量 每創(chuàng)建一個(gè)下拉菜單,都存儲(chǔ)到這個(gè)對(duì)象中,全局管理創(chuàng)建的每一個(gè)下拉菜單。 static Obj = {}; constructor(_label) { super("p"); this.label = _label; // 創(chuàng)建HTML結(jié)構(gòu) this.render(); // 設(shè)置樣式 this.setStyle(); // 鼠標(biāo)滑入滑出點(diǎn)擊,聚焦失焦,點(diǎn)擊事件 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; // 當(dāng)點(diǎn)擊時(shí)修改當(dāng)前顯示的內(nèi)容,重設(shè)樣式,并拋發(fā)事件告知外部當(dāng)前的內(nèi)容。 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()); } // 修改菜單當(dāng)前顯示的內(nèi)容并并拋發(fā)數(shù)據(jù) 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); } // 根據(jù)指定的list創(chuàng)建下拉菜單選項(xiàng)。 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; // 讀取所有城市數(shù)據(jù)并解析為對(duì)象,同步讀取。 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); // 根據(jù)請(qǐng)求頭的url解析接口類型 let type = req.url.trim().split("?")[0].replace(/\//g,""); console.log(type); // 根據(jù)請(qǐng)求頭的url解析傳入的參數(shù) 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); // 根據(jù)接口類型查找數(shù)據(jù)。 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("開(kāi)啟服務(wù)成功"); }
{
"北京": {
"北京": ["東城區(qū)", "西城區(qū)", "崇文區(qū)", "宣武區(qū)", "朝陽(yáng)區(qū)", "豐臺(tái)區(qū)", "石景山區(qū)", "海淀區(qū)", "門頭溝區(qū)", "房山區(qū)", "通州區(qū)", "順義區(qū)", "昌平區(qū)", "大興區(qū)", "平谷區(qū)", "懷柔區(qū)", "密云縣", "延慶縣", "其他"]
},
"天津": {
"天津": ["和平區(qū)", "河?xùn)|區(qū)", "河西區(qū)", "南開(kāi)區(qū)", "河北區(qū)", "紅撟區(qū)", "濱海新區(qū)", "東麗區(qū)", "西青區(qū)", "津南區(qū)", "北辰區(qū)", "寧河區(qū)", "武清區(qū)", "靜海縣", "寶坻區(qū)", "薊縣", "塘沽區(qū)", "漢沽區(qū)", "大港區(qū)", "寶坻區(qū)", "其他"]
},
}
以上就是關(guān)于“怎么使用JS實(shí)現(xiàn)三級(jí)聯(lián)動(dòng)菜單”這篇文章的內(nèi)容,相信大家都有了一定的了解,希望小編分享的內(nèi)容對(duì)大家有幫助,若想了解更多相關(guān)的知識(shí)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。