Idea: cada menú desplegable, como componente, puede recibir un conjunto de datos y generar diferentes opciones de menú basadas en diferentes contenidos de datos. La correlación entre los tres niveles se logra mediante el lanzamiento de eventos. Los datos se obtienen del fondo.
Al hacer clic en el menú de la provincia para seleccionar Shaanxi, el componente del menú descartará la provincia actual mediante el lanzamiento de eventos. Después de conocer la provincia, puede obtener los datos de la ciudad en la provincia en segundo plano. Etcétera.
Efecto de realización:
## URL: http://10.9.72.245:4010
## Método: "GET"
## Formato de datos:
Solicitud: QueryString
Respuesta: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
nombre de la interfaz de la provincia: /getProvince
Request
: Sin parámetros
Respuesta: { "provincia":["Beijing","Tianjin","Hebei",...]}
nombre de interfaz:/getCity
solicitud:?province="Hebei"
respuesta: {"ciudad ":["Shijiazhuang", "Tangshan", "Qinhuangdao",...]}
nombre de la interfaz: /getCounty
solicitud: ?city="Shijiazhuang"
respuesta: {"county":["Distrito de Chang'an ", "Distrito de Qiaodong", "Distrito de Qiaoxi",...]}
<!DOCTYPE html> <html> <cabeza> <meta juego de caracteres="UTF-8"> <meta nombre="viewport" content="ancho=ancho-dispositivo, escala-inicial=1.0"> <título>Documento</título> </cabeza> <cuerpo> <tipo de script="módulo"> importar QueryString desde './js/QueryString.js'; importar DropDownMemu desde './js/DropDownMemu.js'; let ciudadInfo = {}; inicio(); función inicio(){ ajax("http://10.9.72.245:4010","getProvince").luego(successFunction).catch(failFunction); } //Ejecutar después de una comunicación ajax exitosa: función exitosaFunción(_data){ dejar datos = JSON.parse(_data); dejar clave = Object.keys(datos)[0]; datos = Objeto.valores(datos)[0]; if(DropDownMemu.Obj[clave]){ DropDownMemu.Obj[clave].list = datos; DropDownMemu.Obj[clave].nombre = datos[0]; }demás{ let memu = new DropDownMemu(clave); memu.addEventListener("cambiar",changeHandler); memu.lista = datos; memu.nombre =datos[0]; memu.appendTo("cuerpo"); cityInfo[clave] = datos[0]; } } // Cuando el contenido de la pantalla del menú cambia, recibe el evento generado por el menú y obtiene la información contenida en el evento, como {"province":"Shaanxi"} o {"city":"Xi'an"} función changeHandler(e){ dejar clave = e.currentTarget.label; cityInfo[clave] = e.data[clave]; let nombre_interfaz; si(e.data.provincia){ nombreInterfaz = "getCiudad"; }si no (e.data.city){ nombreInterfaz = "getCounty"; }demás{ devolver } ajax("http://10.9.72.245:4010",nombredeinterfaz,infociudad).luego(funciónsuccesse).catch(funciónfail); } /* comunicación ajax: Lista de parámetros: url: dirección de servicio en segundo plano tipo de interfaz: tipo de interfaz, como "getProvince" datos: datos transmitidos, por ejemplo: {"provincia":"Shaanxi"} Tipo de comunicación: solicitud predeterminada "GET" para enviar datos en formato json: el valor predeterminado es falso */ función ajax(url,tipodeinterfaz,datos,tipo="obtener",json=false){ tipo = tipo.toUpperCase(); let o = tipo==="OBTENER" nulo: datos; if(datos) datos = json? JSON.stringify(datos): QueryString.stringify(datos); más datos = ""; devolver nueva Promesa(función(resolver,rechazar){ let xhr = nuevo XMLHttpRequest(); xhr.open(tipo,url + "/" + tipo de interfaz + (tipo==="GET"? "?"+datos: "")); xhr.enviar(o); xhr.onreadystatechange = función(){ si(xhr.readyState===4 && xhr.status===200){ resolver (xhr.respuesta); }si no(xhr.readyState===4){ resolver (xhr.status); } } xhr.onerror= función(){ rechazar (xhr.respuesta); } }) } //Ejecutar la función failFunction(_err){ cuando falla la comunicación ajax consola.log(_err); } </script> </cuerpo> </html>
componente de importación de clase DropDownMemu desde "./Component.js"; exportar la clase predeterminada DropDownMemu extiende el componente { _list; // Opciones actuales del menú desplegable. _name; //El nombre seleccionado actualmente para mostrar, por ejemplo: "Beijing" etiqueta; //La etiqueta del menú desplegable actual, provincia ciudad condado spanLabel; // Contenedor de etiquetas spanCaret; // Triangle ul; // Contenedor de opciones desplegables bool=false; // Controla los eventos del mouse, el estado de enfoque o la selección, no activa el efecto de deslizamiento hacia adentro y hacia afuera. //Establece el estilo del menú desplegable según los diferentes estados. DESPLEGABLE estático = Símbolo(); ESTÁTICO POR DEFECTO = Símbolo(); // Las variables globales estáticas se almacenan en este objeto cada vez que se crea un menú desplegable, y cada menú desplegable creado se administra globalmente. Objeto estático = {}; constructor(_etiqueta) { super("p"); this.label = _label; //Crear estructura HTML this.render(); //Establece el estilo this.setStyle(); // El mouse se desliza hacia adentro y hacia afuera y hace clic, el foco está desenfocado, el evento de clic 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("hacer clic", e => this.mouseHandler(e)); } controlador de ratón(e){ cambiar(e.tipo){ caso "mouseenter": si (este.bool) regresa this.elem.style.backgroundColor = "#e6e6e6"; romper; caso "mouseleave": si (este.bool) regresa this.elem.style.backgroundColor = "#fff"; romper; caso "enfocarse": this.setState(DropDownMemu.DROPDOWN); this.bool = verdadero; romper; caso "enfoque": this.setState(DropDownMemu.DEFAULT); this.bool = falso; caso "clic": if(e.target.constructor!== HTMLLIElement) retorno this._name = e.target.textContent; // Modifica el contenido que se muestra actualmente al hacer clic, restablece el estilo y lanza eventos para informar al mundo externo sobre el contenido actual. this.setContent(); let evt = new FocusEvent("enfoque"); this.elem.dispatchEvent(evt); } } establecer nombre(_nombre){ this._name = _nombre; this.setContent(); } obtener nombre(){ devolver this._name; } establecer lista(_list){ this._list = _list; this.ul.innerHTML = ""; this.ul.appendChild(this.createLi()); } // Modifica el contenido del menú que se muestra actualmente y arroja datos setContent(_name){ este._nombre = _nombre || este._nombre; this.spanLabel.textContent = this._name; let evt = new MouseEvent("cambiar"); if(!evt.datos) evt.datos = {} evt.data[this.label] = this._name; this.dispatchEvent(evt); } //Crea una opción de menú desplegable basada en la lista especificada. crearLi(_lista){ esta._lista = _lista || esta._lista; let elem = document.createDocumentFragment(); this._list.forEach((elemento, índice) => { let li = document.createElement("li"); li.textContent = artículo; Objeto.assign(li.estilo, { altura de línea: "26px", relleno: "0 15px", }) elem.appendChild(li); }) elemento de retorno; } establecerEstado(tipo){ cambiar(tipo){ caso DropDownMemu.DROPDOWN: this.elem.style.backgroundColor = "#e6e6e6"; this.ul.style.display = "bloquear"; romper; caso DropDownMemu.DEFAULT: this.elem.style.backgroundColor = "#fff"; this.ul.style.display = "ninguno"; romper; } } agregar a (padre) { super.appendTo(padre); DropDownMemu.Obj[this.label] = esto; } prestar() { 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); } establecerEstilo() { Objeto.assign(este.elem.estilo, { flotador: "izquierda", altura mínima: "20px", ancho mínimo: "80px", color: "#333", peso de fuente: "normal", textAlign: "centro", espacio en blanco: "nowrap", verticalAlign: "medio", cursor: "puntero", borde: "1px sólido #ccc", borderRadius: "4px", Color de fondo: "#fff", relleno: "6px 12px", Tamaño de fuente: "14px", selección de usuario: "ninguno", margenDerecha: "100px", posición:"relativa", }); Object.assign(this.spanLabel.style, { flotador: "izquierda", relleno: "0 5px" }) Object.assign(este.spanCaret.style, { mostrar: "bloque en línea", verticalAlign: "medio", borderTop: "4px discontinuo", borderRight: "4px sólido transparente", borderLeft: "4px sólido transparente", }) Object.assign(este.ul.estilo, { listStyle: "ninguno", posición: "absoluta", arriba: "100%", izquierda: "0", Índice z: "1000", ancho mínimo: "100px", relleno: "5px 0px", margen: "2px 0 0", Tamaño de fuente: "14px", textAlign: "izquierda", Color de fondo: "#fff", borde: "1px sólido rgba(0, 0, 0, 0.15)", borderRadius: "4px", boxShadow: "0 6px 12px rgba(0, 0, 0, 0.175)", mostrar: "ninguno", }) } }
exportar la clase predeterminada El componente extiende EventTarget{ elemento; constructor(_tipo){ súper(); this.elem = this.createElem(_type); } crearElem(_tipo){ let elem = document.createElement(_type); elemento de retorno; } agregar a (padre) { if(typeof parent==="cadena") padre = document.querySelector(padre); parent.appendChild(este.elem); } }
let http = require("http"); let cadena de consulta = require("cadena de consulta"); dejar datos, requiere, res; // Lee todos los datos de la ciudad, los analiza en objetos y los lee sincrónicamente. let fs = requerir("fs"); let allCityInfo = JSON.parse(fs.readFileSync('./city.json')); dejar servidor = http.createServer(listenerHandler); servidor.listen(4010,"10.9.72.245",listenerDoneHandler); función oyenteHandler(_req,_res){ solicitud = _solicitud; res = _res; res.writeHead(200,{ "tipo de contenido":"text/html;charset=utf-8", "Control-de-acceso-permitir-origen":"*", "Control-de-acceso-permitir-encabezados":"*", }); datos=""; req.on("datos",función(_datos){ datos=_datos; }) req.on("fin",receiveHandler); } función recibirHandler(){ // console.log(allCityInfo); // Analiza el tipo de interfaz según la URL del encabezado de la solicitud let type = req.url.trim().split("?")[0].replace(///g,""); consola.log(tipo); // Analiza los parámetros entrantes según la URL del encabezado de la solicitud if(req.method.toUpperCase()==="GET"){ if(req.url.includes("favicon.ico")) return res.end(); else datos = req.url.includes("?") ? req.url.split("?")[1] : ""; } intentar{ datos = JSON.parse(datos); }atrapar{ datos = querystring.parse(datos); } consola.log(datos); //Buscar datos según el tipo de interfaz. dejar lista = {}; cambiar(tipo){ caso "getProvince": lista.provincia = Object.keys(allCityInfo); romper; caso "getCity": lista.ciudad = Object.keys(allCityInfo[data.province]); romper; caso "getCounty": lista.condado = allCityInfo[data.province][data.city]; romper; } consola.log(lista); res.write(JSON.stringify(lista)); res.end() } función oyenteDoneHandler(){ console.log("El servicio se inició correctamente"); }
{
"Pekín": {
"Beijing": ["Distrito Dongcheng", "Distrito Xicheng", "Distrito Chongwen", "Distrito Xuanwu", "Distrito Chaoyang", "Distrito Fengtai", "Distrito Shijingshan", "Distrito Haidian", "Distrito Mentougou", "Distrito de Fangshan", "Distrito de Tongzhou", "Distrito de Shunyi", "Distrito de Changping", "Distrito de Daxing", "Distrito de Pinggu", "Distrito de Huairou", "Condado de Miyun", "Condado de Yanqing", "Otros"]
} ,
"Tianjín": {
"Tianjin": ["Distrito de Heping", "Distrito de Hedong", "Distrito de Hexi", "Distrito de Nankai", "Distrito de Hebei", "Distrito de Hongjiao", "Nuevo distrito de Binhai", "Distrito de Dongli", "Distrito de Xiqing" "Distrito", "Distrito de Jinnan", "Distrito de Beichen", "Distrito de Ninghe", "Distrito de Wuqing", "Condado de Jinghai", "Distrito de Baodi", "Jixian", "Distrito de Tanggu", "Distrito de Hangu", "Distrito de Dagang ", "Baodi District", "Otros"]
},
}
Lo anterior es una explicación detallada del menú de enlace de tres niveles usando JS (con explicación de ideas). Para obtener más información, preste atención a otros artículos relacionados sobre PHP. Sitio web chino!