1. 程式人生 > >聯級選擇器(仿element-ui),不過我用的是jq寫的!

聯級選擇器(仿element-ui),不過我用的是jq寫的!

在做元件之前,一般我都是把HTML結構先寫出來的,最終我們需要變成這樣的結構

    <div class="cascader-menus">
        <ul class="menus">
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
        </ul>
        <ul class="menus">
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
        </ul>
        <ul class="menus">
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
            <li>文字</li>
        </ul>
    </div>                       

然後是樣式:

/*這裡採用浮動是為了讓寬度自適應*/
    .cascader-menus{
        float: left;
        font-size: 0;
        border: 1px #ccc solid;
    }
    /*佈局用的inline-block,並且溢位會有滾動條*/
    .cascader-menus .menus{
        display: inline-block;
        min-width: 160px;
        height: 204px;
        overflow-y: auto;
        border-right: 1px #ccc solid;
    }
    .cascader-menus .menus:last-child{
        border-right: none;
    }
    .cascader-menus .menus li{
        font-size: 14px;
        padding: 0 10px;
        line-height: 30px;
        height: 30px;
    }
    .cascader-menus .menus li:hover {
        cursor: pointer;
        background-color: #eee;
    }
    /*點選的時候需要加的樣式*/
    .cascader-menus .menus li.active {
        background-color: #eee;
    }

資料結構(直接從element-ui複製的):

var lists = [
    {
        value: 'zhinan',
        label: '指南',
        children: [
            {
                value: 'shejiyuanze',
                label: '設計原則',
                children: [{
                    value: 'yizhi',
                    label: '一致'
                }, {
                    value: 'fankui',
                    label: '反饋'
                }, {
                    value: 'xiaolv',
                    label: '效率'
                }, {
                    value: 'kekong',
                    label: '可控'
                }]
            },
            {
                value: 'daohang',
                label: '導航',
                children: [
                    {
                        value: 'cexiangdaohang',
                        label: '側向導航'
                    },
                    {
                        value: 'dingbudaohang',
                        label: '頂部導航'
                    }
                ]
            }
        ]
    },
    {
        value: 'zujian',
        label: '元件',
        children: [{
            value: 'basic',
            label: 'Basic',
            children: [{
                value: 'layout',
                label: 'Layout 佈局'
            }, {
                value: 'color',
                label: 'Color 色彩'
            }, {
                value: 'typography',
                label: 'Typography 字型'
            }, {
                value: 'icon',
                label: 'Icon 圖示'
            }, {
                value: 'button',
                label: 'Button 按鈕'
            }]
        }, {
            value: 'form',
            label: 'Form',
            children: [{
                value: 'radio',
                label: 'Radio 單選框'
            }, {
                value: 'checkbox',
                label: 'Checkbox 多選框'
            }, {
                value: 'input',
                label: 'Input 輸入框'
            }, {
                value: 'input-number',
                label: 'InputNumber 計數器'
            }, {
                value: 'select',
                label: 'Select 選擇器'
            }, {
                value: 'cascader',
                label: 'Cascader 級聯選擇器'
            }, {
                value: 'switch',
                label: 'Switch 開關'
            }, {
                value: 'slider',
                label: 'Slider 滑塊'
            }, {
                value: 'time-picker',
                label: 'TimePicker 時間選擇器'
            }, {
                value: 'date-picker',
                label: 'DatePicker 日期選擇器'
            }, {
                value: 'datetime-picker',
                label: 'DateTimePicker 日期時間選擇器'
            }, {
                value: 'upload',
                label: 'Upload 上傳'
            }, {
                value: 'rate',
                label: 'Rate 評分'
            }, {
                value: 'form',
                label: 'Form 表單'
            }]
        }, {
            value: 'data',
            label: 'Data',
            children: [{
                value: 'table',
                label: 'Table 表格'
            }, {
                value: 'tag',
                label: 'Tag 標籤'
            }, {
                value: 'progress',
                label: 'Progress 進度條'
            }, {
                value: 'tree',
                label: 'Tree 樹形控制元件'
            }, {
                value: 'pagination',
                label: 'Pagination 分頁'
            }, {
                value: 'badge',
                label: 'Badge 標記'
            }]
        }, {
            value: 'notice',
            label: 'Notice',
            children: [{
                value: 'alert',
                label: 'Alert 警告'
            }, {
                value: 'loading',
                label: 'Loading 載入'
            }, {
                value: 'message',
                label: 'Message 訊息提示'
            }, {
                value: 'message-box',
                label: 'MessageBox 彈框'
            }, {
                value: 'notification',
                label: 'Notification 通知'
            }]
        }, {
            value: 'navigation',
            label: 'Navigation',
            children: [{
                value: 'menu',
                label: 'NavMenu 導航選單'
            }, {
                value: 'tabs',
                label: 'Tabs 標籤頁'
            }, {
                value: 'breadcrumb',
                label: 'Breadcrumb 麵包屑'
            }, {
                value: 'dropdown',
                label: 'Dropdown 下拉選單'
            }, {
                value: 'steps',
                label: 'Steps 步驟條'
            }]
        }, {
            value: 'others',
            label: 'Others',
            children: [{
                value: 'dialog',
                label: 'Dialog 對話方塊'
            }, {
                value: 'tooltip',
                label: 'Tooltip 文字提示'
            }, {
                value: 'popover',
                label: 'Popover 彈出框'
            }, {
                value: 'card',
                label: 'Card 卡片'
            }, {
                value: 'carousel',
                label: 'Carousel 走馬燈'
            }, {
                value: 'collapse',
                label: 'Collapse 摺疊面板'
            }]
        }]
    },
    {
        value: 'ziyuan',
        label: '資源',
        children: [{
            value: 'axure',
            label: 'Axure Components'
        }, {
            value: 'sketch',
            label: 'Sketch Templates'
        }, {
            value: 'jiaohu',
            label: '元件互動文件'
        }]
    },
    {"value": 1, label: 'xxx'},
]

然後是JS:

//建構函式
	function Cascader(id,data,fn){
		//把建立好的“聯級選擇器”插入到哪個元素內
		this.$box = $("#"+id);
		//data: 是要填充的資料
		this.init(data);
		
		//對外提供的介面函式
		this.clickHandle = fn || function(){};
		
		//最外層的容器,後期需要把createEl()方法建立的內容都插入到這裡面的
		this.$wrap = null;
	}
	
	Cascader.prototype = {
		constructor: Cascader,
		init: function(data){
			var This = this;
			this.$wrap = $("<div class='cascader-menus'></div>")
			//建立裡面的元素
			this.createEl(data,function($ul){
				This.$wrap.append($ul);
				This.$box.append(This.$wrap)
			});
			console.log(data)
		},
		createEl: function(data,fn) {
			var This = this;
			//建立完成以後回撥函式
			var fn = fn || function(){};
			var $ul = $("<ul class='menus'></ul>");
			
			//建立li,並把li插入到ul中
			for (var i=0;i<data.length;i++) {
				var $li = $("<li>"+ data[i].label +"</li>");
				//給每一個Li加點選事件,點選以後顯示子選單,這裡最好採用閉包的形式,不然i傳遞不進去,當然也可以用es6的let(不過這裡沒有bable,瀏覽器會不支援let的,在vue-cli中的話就沒問題了)
				(function(i){
					$li.click(function(){
						$(this).addClass('active').siblings().removeClass('active');
						//先需要清除掉後面所有的選單
						$ul.nextAll().remove();
						if (data[i].children && data[i].children.length) {
							//建立子選單
							This.createEl(data[i].children,function(ul){
								//把建立好的子選單插入到上一個選單的後面
								$ul.after(ul);
							});
						}
						//對外提供的點選介面函式,並把資料給傳遞出去
						This.clickHandle(data[i]);
					})
				})(i)
				$ul.append($li);
			}
			
			//建立完成以後回撥函式
			fn($ul)
		}
	}

使用:

//呼叫
		var c1 = new Cascader("box",lists,function(mes){
			console.log(mes)
		});
這個box就是個<div id="box"></div>