Heim  >  Artikel  >  Web-Frontend  >  In einem Artikel wird ausführlich erläutert, wie man ein dreistufiges Verknüpfungsmenü mit JS implementiert (mit Erläuterung der Ideen).

In einem Artikel wird ausführlich erläutert, wie man ein dreistufiges Verknüpfungsmenü mit JS implementiert (mit Erläuterung der Ideen).

藏色散人
藏色散人nach vorne
2022-08-10 17:51:092727Durchsuche

Idee: Jedes Dropdown-Menü kann als Komponente einen Datensatz empfangen und basierend auf unterschiedlichen Dateninhalten unterschiedliche Menüoptionen generieren. Die Korrelation zwischen den drei Ebenen wird durch Event Throwing erreicht. Daten werden aus dem Hintergrund gewonnen.

Wenn Sie auf das Provinzmenü klicken, um Shaanxi auszuwählen, wirft die Menükomponente die aktuelle Provinz durch Ereignisauswurf aus. Nachdem Sie die Provinz kennen, können Sie die Stadtdaten unter der Provinz aus dem Hintergrund abrufen. Und so weiter. [Verwandte Empfehlungen: JavaScript-Video-Tutorial]

Erfolgseffekt:

Informationen zur Back-End-Schnittstelle:

Dreistufige kaskadierende Menüoberfläche:

## URL: http://10.9 . 72.245:4010

## Methode: „GET“

## Datenformat:

Anfrage: QueryString

Antwort: JSON

Schnittstellenname:

1. http://10.9.72.245:4010 /getProvince

2. http://10.9.72.245:4010/getCity

3. http://10.9.72.245:4010/getCounty

Holen Sie sich die Provinzschnittstelle

Schnittstellenname: /getProvince

Anfrage: keine Parameter

Antwort:{"province":["Beijing","Tianjin","Hebei",...]}

Stadtschnittstelle abrufen:

Schnittstellenname:/getCity

Anfrage:?province="Hebei"

Antwort: {"city":["Shijiazhuang", "Tangshan", "Qinhuangdao",...]}

Kreisschnittstelle abrufen:

Schnittstellenname: /getCounty

Anfrage: ?city="Shijiazhuang"

Antwort: {"County":["Chang'an District", "Qiaodong District", "Qiaoxi District",...]}

Spezifische Implementierung:

1 Erstellen Sie Dropdown-Menükomponenten und Frontend und Back-End-Kommunikation:

<!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 &#39;./js/QueryString.js&#39;;
        import DropDownMemu from &#39;./js/DropDownMemu.js&#39;;
 
        let cityInfo = {};
        init();
        function init(){
            ajax("http://10.9.72.245:4010","getProvince").then(succeseFunction).catch(failFunction);
        }
        // ajax通信成功后执行:
        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];
            }
        }
        // 当菜单显示内容改变时接收到菜单抛发出的事件并获取事件中携带的信息例如{"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通信:
            参数列表:
            url: 后台服务地址
            interfaceType:接口类型,如 "getProvince"
            data:传输的数据,例如:{"province":"陕西"}
            通信类型type:默认"GET"请求
            是否以json格式发送数据:默认为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通信失败时执行
        function failFunction(_err){
            console.log(_err);
        }
 
 
    </script>
</body>
</html>

2, Dropdown-Menükomponente: DropDownMemu-Klasse

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",
        })
    }
}

3. Die übergeordnete Komponente von nodejs:

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);
    }
}

5 .json im JSON-Format, wie unten gezeigt:

{

„Beijing“: {

„Beijing“: [„Dongcheng District“, „Xicheng District“, „Chongwen District“, „Xuanwu District“, „Bezirk Chaoyang“, „Bezirk Fengtai“, „Bezirk Shijingshan“, „Bezirk Haidian“, „Bezirk Mentougou“, „Bezirk Fangshan“, „Bezirk Tongzhou“, „Bezirk Shunyi“, „Bezirk Changping“, „Bezirk Daxing“ , „Bezirk Pinggu“, „Bezirk Huairou“, „Bezirk Miyun“, „Bezirk Yanqing“, „Andere“]

},

„Tianjin“: {

„Tianjin“: [„Heping District“, „Hedong District“, „Hexi District“, „Nankai District“, „Hebei District“, „Hongjie District“, „Binhai New District“, „Dongli District“, „Xi“ Qing-Bezirk“, „Jinnan-Bezirk“, „Beichen-Bezirk“, „Ninghe-Bezirk“, „Wuqing-Bezirk“, „Jinghai-Bezirk“, „Baodi-Bezirk“, „Jixian“, „Tanggu-Bezirk“, „Hangu-Bezirk“, „Dagang“. Bezirk“, „Bezirk Baodi“, „Andere“]

},

}

Das obige ist der detaillierte Inhalt vonIn einem Artikel wird ausführlich erläutert, wie man ein dreistufiges Verknüpfungsmenü mit JS implementiert (mit Erläuterung der Ideen).. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen